in tools/NLS/Xlat/Xlat.cpp [389:868]
int Xlat_main(int argC, XMLCh** argV)
{
init_Globals();
//
// Lets check the parameters and save them away in globals for use by
// the processing code.
//
if (!parseParms(argC, argV))
{
wprintf(L"Usage:\n NLSXlat /SrcRoot=xx /OutPath=xx /OutFmt=xx /Locale=xx\n\n");
return ErrReturn_BadParameters;
}
{
// Nest entire code in an inner block.
DOMDocument* srcDoc;
const unsigned int bufSize = 4095;
XMLCh *tmpFileBuf = new XMLCh [bufSize + 1];
tmpFileBuf[0] = 0;
XMLCh *tmpXMLStr = XMLString::transcode("/XMLErrList_");
XMLCh *tmpXMLStr2 = XMLString::transcode(".Xml");
try
{
try
{
// Build the input file name
XMLString::catString(tmpFileBuf, gSrcRoot);
XMLString::catString(tmpFileBuf, gRelativeInputPath);
XMLString::catString(tmpFileBuf, gLocale);
XMLString::catString(tmpFileBuf, tmpXMLStr );
XMLString::catString(tmpFileBuf, gLocale);
XMLString::catString(tmpFileBuf, tmpXMLStr2 );
XMLString::release(&tmpXMLStr);
XMLString::release(&tmpXMLStr2);
//
// Ok, lets invoke the DOM parser on the input file and build
// a DOM tree. Turn on validation when we do this.
//
XercesDOMParser parser;
parser.setValidationScheme(AbstractDOMParser::Val_Always);
XlatErrHandler errHandler;
parser.setErrorHandler(&errHandler);
parser.parse(tmpFileBuf);
srcDoc = parser.adoptDocument();
}
catch(const XMLException& toCatch)
{
parseError(toCatch);
}
delete tmpFileBuf;
//
// Use the output format parm to create the correct kind of output
// formatter.
//
XlatFormatter* formatter = 0;
switch(gOutFormat)
{
case OutFormat_CppSrc :
formatter = new CppSrcFormatter;
break;
case OutFormat_Win32RC :
formatter = new Win32RCFormatter;
break;
case OutFormat_MsgCatalog :
formatter = new MsgCatFormatter;
break;
case OutFormat_ResBundle:
formatter = new ICUResBundFormatter;
break;
default :
wprintf(L"Unknown formatter type enum\n\n");
throw ErrReturn_Internal;
}
//
// Lets handle the root element stuff first. This one holds any over
// all information.
//
DOMElement* rootElem = srcDoc->getDocumentElement();
tmpXMLStr = XMLString::transcode("Locale");
const XMLCh* localeStr = rootElem->getAttribute(tmpXMLStr);
XMLString::release(&tmpXMLStr);
// Make sure that the locale matches what we were given
if (XMLString::compareString(localeStr, gLocale))
{
wprintf(L"The file's locale does not match the target locale\n");
throw ErrReturn_LocaleErr;
}
//
// Get a list of all the MsgDomain children. These each hold one of
// the sets of (potentially separately) loadable messages. More
// importantly they all have their own error id space.
//
tmpXMLStr = XMLString::transcode("MsgDomain");
DOMNodeList* msgSetList = rootElem->getElementsByTagName(tmpXMLStr);
XMLString::release(&tmpXMLStr);
//
// Loop through them and look for the domains that we know are
// supposed to be there.
//
const XMLSize_t count = msgSetList->getLength();
//
// Normalize locale string
//
// locale = ll[[_CC][_VARIANT]]
// where ll is language code
// CC is country code
// VARIANT is variant code
//
XMLCh normalizedLocale[256];
normalizedLocale[0] = localeStr[0];
normalizedLocale[1] = localeStr[1];
normalizedLocale[2] = 0;
XMLString::lowerCase(normalizedLocale);
if (XMLString::stringLen(localeStr) > 2)
{
XMLString::catString(&(normalizedLocale[2]), &(localeStr[2]));
XMLString::upperCase(&(normalizedLocale[2]));
}
//
// Ok, its good enough to get started. So lets call the start output
// method on the formatter.
//
formatter->startOutput(normalizedLocale, gOutPath);
//
// For each message domain element, we call start and end domain
// events bracketed around the loop that sends out each message
// in that domain.
//
// Within each domain, we check for the Warning, Error, and Validity
// subelements, and then iterate all the messages in each one.
//
for (unsigned int index = 0; index < count; index++)
{
// We know its a DOM Element, so go ahead and cast it
DOMNode* curNode = msgSetList->item(index);
const DOMElement* curElem = (const DOMElement*)curNode;
//
// Get some of the attribute strings that we need, and transcode
// couple that need to be in local format.
//
tmpXMLStr = XMLString::transcode("Domain");
const XMLCh* domainStr = curElem->getAttribute(tmpXMLStr );
XMLString::release(&tmpXMLStr);
//
// Look at the domain and set up our application specific info
// that is on a per-domain basis. We need to indicate what the
// name of the header is and what the namespace is that they
// codes will go into
//
XMLCh* headerName = 0;
XMLCh* errNameSpace = 0;
if (!XMLString::compareString(domainStr, XMLUni::fgXMLErrDomain))
{
headerName = XMLString::transcode("XMLErrorCodes.hpp");
errNameSpace = XMLString::transcode("XMLErrs");
}
else if (!XMLString::compareString(domainStr, XMLUni::fgValidityDomain))
{
headerName = XMLString::transcode("XMLValidityCodes.hpp");
errNameSpace = XMLString::transcode("XMLValid");
}
else if (!XMLString::compareString(domainStr, XMLUni::fgExceptDomain))
{
headerName = XMLString::transcode("XMLExceptMsgs.hpp");
errNameSpace = XMLString::transcode("XMLExcepts");
}
else if (!XMLString::compareString(domainStr, XMLUni::fgXMLDOMMsgDomain))
{
headerName = XMLString::transcode("XMLDOMMsg.hpp");
errNameSpace = XMLString::transcode("XMLDOMMsg");
}
else
{
// Not one of ours, so skip it
continue;
}
//
// Lets try to create the header file that was indicated for
// this domain.
//
tmpFileBuf = new XMLCh [bufSize + 1];
tmpFileBuf[0] = 0;
XMLString::catString(tmpFileBuf, gOutPath);
XMLString::catString(tmpFileBuf, headerName);
char *tmpFileBufCh = XMLString::transcode(tmpFileBuf);
FILE* outHeader = fopen(tmpFileBufCh, "wt+");
XMLString::release(&tmpFileBufCh);
if ((!outHeader) || (fwide(outHeader, 1) < 0))
{
wprintf(L"Could not open domain header file: %s\n\n", xmlStrToPrintable(tmpFileBuf));
releasePrintableStr
XMLString::release(&tmpFileBuf);
XMLString::release(&headerName);
XMLString::release(&errNameSpace);
throw ErrReturn_OutFileOpenFailed;
}
delete tmpFileBuf;
//
// Write out the opening of the class they are nested within, and
// the header protection define.
//
fwprintf(outHeader, L"// This file is generated, don't edit it!!\n\n");
fwprintf(outHeader, L"#if !defined(XERCESC_INCLUDE_GUARD_ERRHEADER_%s)\n", xmlStrToPrintable(errNameSpace) );
releasePrintableStr
fwprintf(outHeader, L"#define XERCESC_INCLUDE_GUARD_ERRHEADER_%s\n\n", xmlStrToPrintable(errNameSpace) );
releasePrintableStr
// If its not the exception domain, then we need a header included
if (XMLString::compareString(domainStr, XMLUni::fgExceptDomain))
fwprintf(outHeader, L"#include <xercesc/framework/XMLErrorReporter.hpp>\n");
// Write out the namespace declaration
fwprintf(outHeader, L"#include <xercesc/util/XercesDefs.hpp>\n");
fwprintf(outHeader, L"#include <xercesc/dom/DOMError.hpp>\n\n");
fwprintf(outHeader, L"namespace XERCES_CPP_NAMESPACE {\n\n");
// Now the message codes
fwprintf(outHeader, L"class %s\n{\npublic :\n enum Codes\n {\n", xmlStrToPrintable(errNameSpace) );
releasePrintableStr
// Tell the formatter that a new domain is starting
formatter->startDomain
(
domainStr
, errNameSpace
);
//
// Force out the first message, which is always implicit and is
// the 'no error' entry for that domain.
//
unsigned int count = 0;
fwprintf(outHeader, L" %-32s = %d\n", longChars("NoError"), count++);
//
// Loop through the children of this node, which should take us
// through the optional Warning, Error, and Validity subsections.
//
DOMNode* typeNode = curElem->getFirstChild();
bool typeGotten[3] = { false, false, false };
while (typeNode)
{
// Skip over text nodes or comment nodes ect...
if (typeNode->getNodeType() != DOMNode::ELEMENT_NODE)
{
typeNode = typeNode->getNextSibling();
continue;
}
// Convert it to an element node
const DOMElement* typeElem = (const DOMElement*)typeNode;
// Now get its tag name and convert that to a message type enum
const XMLCh* typeName = typeElem->getTagName();
MsgTypes type;
tmpXMLStr = XMLString::transcode("Warning");
XMLCh* tmpXMLStr2 = XMLString::transcode("Error");
XMLCh* tmpXMLStr3 =XMLString::transcode("FatalError");
if (!XMLString::compareString(typeName, tmpXMLStr ))
{
type = MsgType_Warning;
typeGotten[0] = true;
}
else if (!XMLString::compareString(typeName, tmpXMLStr2 ))
{
type = MsgType_Error;
typeGotten[1] = true;
}
else if (!XMLString::compareString(typeName, tmpXMLStr3 ))
{
type = MsgType_FatalError;
typeGotten[2] = true;
}
else
{
wprintf(L"Expected a Warning, Error, or FatalError node\n\n");
XMLString::release(&tmpXMLStr);
XMLString::release(&tmpXMLStr2);
XMLString::release(&tmpXMLStr3);
throw ErrReturn_SrcFmtError;
}
XMLString::release(&tmpXMLStr);
XMLString::release(&tmpXMLStr2);
XMLString::release(&tmpXMLStr3);
// Call the start message type event
formatter->startMsgType(type);
// Enumerate the messages under this subsection
enumMessages
(
typeElem
, formatter
, outHeader
, type
, count
);
// Call the end message type event
formatter->endMsgType(type);
// Move to the next child of the source element
typeNode = typeNode->getNextSibling();
}
//
// For any that we did not get, spit out faux boundary
// values for it.
//
for (unsigned int subIndex = 0; subIndex < 3; subIndex++)
{
if (!typeGotten[subIndex])
{
fwprintf
(
outHeader
, L" , %s%-30s = %d\n"
, xmlStrToPrintable(typePrefixes[subIndex])
, longChars("LowBounds")
, count++
);
releasePrintableStr
fwprintf
(
outHeader
, L" , %s%-30s = %d\n"
, xmlStrToPrintable(typePrefixes[subIndex])
, longChars("HighBounds")
, count++
);
releasePrintableStr
}
}
// Tell the formatter that this domain is ending
formatter->endDomain(domainStr, count);
// Close out the enum declaration
fwprintf(outHeader, L" };\n\n");
//
// Generate the code that creates the simple static methods
// for testing the error types. We don't do this for the
// exceptions header.
//
if (XMLString::compareString(domainStr, XMLUni::fgExceptDomain))
{
fwprintf
(
outHeader
, L" static bool isFatal(const %s::Codes toCheck)\n"
L" {\n"
L" return ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds));\n"
L" }\n\n"
, xmlStrToPrintable(errNameSpace)
);
releasePrintableStr
fwprintf
(
outHeader
, L" static bool isWarning(const %s::Codes toCheck)\n"
L" {\n"
L" return ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds));\n"
L" }\n\n"
, xmlStrToPrintable(errNameSpace)
);
releasePrintableStr
fwprintf
(
outHeader
, L" static bool isError(const %s::Codes toCheck)\n"
L" {\n"
L" return ((toCheck >= E_LowBounds) && (toCheck <= E_HighBounds));\n"
L" }\n\n"
, xmlStrToPrintable(errNameSpace)
);
releasePrintableStr
fwprintf
(
outHeader
, L" static XMLErrorReporter::ErrTypes errorType(const %s::Codes toCheck)\n"
L" {\n"
L" if ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds))\n"
L" return XMLErrorReporter::ErrType_Warning;\n"
L" else if ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds))\n"
L" return XMLErrorReporter::ErrType_Fatal;\n"
L" else if ((toCheck >= E_LowBounds) && (toCheck <= E_HighBounds))\n"
L" return XMLErrorReporter::ErrType_Error;\n"
L" return XMLErrorReporter::ErrTypes_Unknown;\n"
L" }\n"
, xmlStrToPrintable(errNameSpace)
);
releasePrintableStr
fwprintf
(
outHeader
, L" static DOMError::ErrorSeverity DOMErrorType(const %s::Codes toCheck)\n"
L" {\n"
L" if ((toCheck >= W_LowBounds) && (toCheck <= W_HighBounds))\n"
L" return DOMError::DOM_SEVERITY_WARNING;\n"
L" else if ((toCheck >= F_LowBounds) && (toCheck <= F_HighBounds))\n"
L" return DOMError::DOM_SEVERITY_FATAL_ERROR;\n"
L" else return DOMError::DOM_SEVERITY_ERROR;\n"
L" }\n"
, xmlStrToPrintable(errNameSpace)
);
releasePrintableStr
}
// the private default ctor
fwprintf(outHeader, L"\n");
fwprintf(outHeader, L"private:\n");
fwprintf(outHeader, L" // -----------------------------------------------------------------------\n");
fwprintf(outHeader, L" // Unimplemented constructors and operators\n");
fwprintf(outHeader, L" // -----------------------------------------------------------------------\n");
fwprintf(outHeader, L" %s();\n", xmlStrToPrintable(errNameSpace));
releasePrintableStr
// And close out the class declaration, the namespace declaration and the header file
fwprintf(outHeader, L"};\n\n");
fwprintf(outHeader, L"}\n\n");
fwprintf(outHeader, L"#endif\n\n");
fclose(outHeader);
XMLString::release(&headerName);
XMLString::release(&errNameSpace);
}
// Ok, we are done so call the end output method
formatter->endOutput();
// And clean up the stuff we allocated
delete formatter;
}
catch(const ErrReturns retVal)
{
// And call the termination method
if(srcDoc)
delete srcDoc;
return retVal;
}
delete srcDoc;
}
// And call the termination method
release_Globals();
// Went ok, so return success
return ErrReturn_Success;
}