772 lines
29 KiB
C
772 lines
29 KiB
C
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
mcparse.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the parse logic for the Win32 Message Compiler (MC)
|
|
|
|
Author:
|
|
|
|
Steve Wood (stevewo) 22-Aug-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "mc.h"
|
|
|
|
WCHAR * wszMessageType = L"DWORD"; // Init to a known state
|
|
|
|
BOOL
|
|
McParseFile( void )
|
|
{
|
|
unsigned int t;
|
|
BOOL FirstMessageDefinition = TRUE;
|
|
PNAME_INFO p;
|
|
|
|
if (!McOpenInputFile()) {
|
|
fprintf( stderr, "MC: Unable to open %s for input\n", MessageFileName );
|
|
return( FALSE );
|
|
}
|
|
|
|
fprintf( stderr, "MC: Compiling %s\n", MessageFileName );
|
|
while ((t = McGetToken( TRUE )) != MCTOK_END_OF_FILE) {
|
|
switch (t) {
|
|
case MCTOK_MSGIDTYPE_KEYWORD:
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
|
|
wszMessageType = MessageIdTypeName = McMakeString( TokenCharValue );
|
|
} else {
|
|
McInputErrorW( L"Symbol name must follow %s=", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
case MCTOK_MSGTYPEDEF_KEYWORD:
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
|
|
MessageIdTypeMacro = McMakeString( TokenCharValue );
|
|
} else {
|
|
McInputErrorW( L"Symbol name must follow %s=", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
case MCTOK_OUTBASE_KEYWORD:
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
|
|
if (TokenNumericValue == 16) {
|
|
GenerateDecimalMessageValues = FALSE;
|
|
} else if (TokenNumericValue == 10) {
|
|
GenerateDecimalMessageValues = TRUE;
|
|
} else {
|
|
McInputErrorW( L"Illegal value for %s=", TRUE, TokenKeyword->Name );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Number must follow %s=", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
case MCTOK_SEVNAMES_KEYWORD:
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_LEFT_PAREN) {
|
|
if (!McParseNameList( &SeverityNames, FALSE, 0x3L )) {
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Left parenthesis name must follow %s=", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
case MCTOK_FACILITYNAMES_KEYWORD:
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_LEFT_PAREN) {
|
|
if (!McParseNameList( &FacilityNames, FALSE, 0xFFFL )) {
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Left parenthesis name must follow %s=", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
case MCTOK_LANGNAMES_KEYWORD:
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_LEFT_PAREN) {
|
|
if (!McParseNameList( &LanguageNames, TRUE, 0xFFFFL )) {
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Left parenthesis name must follow %s=", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
case MCTOK_MESSAGEID_KEYWORD:
|
|
McUnGetToken();
|
|
if (FirstMessageDefinition) {
|
|
FirstMessageDefinition = FALSE;
|
|
McFlushComments();
|
|
if (OleOutput) {
|
|
fputs(
|
|
"//\r\n"
|
|
"// Values are 32 bit values layed out as follows:\r\n"
|
|
"//\r\n"
|
|
"// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1\r\n"
|
|
"// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0\r\n"
|
|
"// +-+-+-+-+-+---------------------+-------------------------------+\r\n"
|
|
"// |S|R|C|N|r| Facility | Code |\r\n"
|
|
"// +-+-+-+-+-+---------------------+-------------------------------+\r\n"
|
|
"//\r\n"
|
|
"// where\r\n"
|
|
"//\r\n"
|
|
"// S - Severity - indicates success/fail\r\n"
|
|
"//\r\n"
|
|
"// 0 - Success\r\n"
|
|
"// 1 - Fail (COERROR)\r\n"
|
|
"//\r\n"
|
|
"// R - reserved portion of the facility code, corresponds to NT's\r\n"
|
|
"// second severity bit.\r\n"
|
|
"//\r\n"
|
|
"// C - reserved portion of the facility code, corresponds to NT's\r\n"
|
|
"// C field.\r\n"
|
|
"//\r\n"
|
|
"// N - reserved portion of the facility code. Used to indicate a\r\n"
|
|
"// mapped NT status value.\r\n"
|
|
"//\r\n"
|
|
"// r - reserved portion of the facility code. Reserved for internal\r\n"
|
|
"// use. Used to indicate HRESULT values that are not status\r\n"
|
|
"// values, but are instead message ids for display strings.\r\n"
|
|
"//\r\n"
|
|
"// Facility - is the facility code\r\n"
|
|
"//\r\n"
|
|
"// Code - is the facility's status code\r\n"
|
|
"//\r\n",
|
|
HeaderFile );
|
|
} else {
|
|
fputs(
|
|
"//\r\n"
|
|
"// Values are 32 bit values layed out as follows:\r\n"
|
|
"//\r\n"
|
|
"// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1\r\n"
|
|
"// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0\r\n"
|
|
"// +---+-+-+-----------------------+-------------------------------+\r\n"
|
|
"// |Sev|C|R| Facility | Code |\r\n"
|
|
"// +---+-+-+-----------------------+-------------------------------+\r\n"
|
|
"//\r\n"
|
|
"// where\r\n"
|
|
"//\r\n"
|
|
"// Sev - is the severity code\r\n"
|
|
"//\r\n"
|
|
"// 00 - Success\r\n"
|
|
"// 01 - Informational\r\n"
|
|
"// 10 - Warning\r\n"
|
|
"// 11 - Error\r\n"
|
|
"//\r\n"
|
|
"// C - is the Customer code flag\r\n"
|
|
"//\r\n"
|
|
"// R - is a reserved bit\r\n"
|
|
"//\r\n"
|
|
"// Facility - is the facility code\r\n"
|
|
"//\r\n"
|
|
"// Code - is the facility's status code\r\n"
|
|
"//\r\n",
|
|
HeaderFile );
|
|
}
|
|
|
|
fputs(
|
|
"//\r\n"
|
|
"// Define the facility codes\r\n"
|
|
"//\r\n",
|
|
HeaderFile );
|
|
|
|
p = FacilityNames;
|
|
while( p ) {
|
|
if (p->Value) {
|
|
fprintf( HeaderFile, GenerateDecimalSevAndFacValues ?
|
|
"#define %-32ws %ld\r\n" :
|
|
"#define %-32ws 0x%lX\r\n",
|
|
p->Value, p->Id
|
|
);
|
|
}
|
|
|
|
p = p->Next;
|
|
}
|
|
fputs(
|
|
"\r\n"
|
|
"\r\n"
|
|
"//\r\n"
|
|
"// Define the severity codes\r\n"
|
|
"//\r\n",
|
|
HeaderFile );
|
|
|
|
p = SeverityNames;
|
|
while( p ) {
|
|
if (p->Value) {
|
|
fprintf( HeaderFile, GenerateDecimalSevAndFacValues ?
|
|
"#define %-32ws %ld\r\n" :
|
|
"#define %-32ws 0x%lX\r\n",
|
|
p->Value, p->Id
|
|
);
|
|
}
|
|
|
|
p = p->Next;
|
|
}
|
|
|
|
fputs(
|
|
"\r\n"
|
|
"\r\n",
|
|
HeaderFile );
|
|
|
|
if (GenerateDebugFile) {
|
|
fputs(
|
|
"//\n"
|
|
"// This file maps message Id values in to a text string that contains\n"
|
|
"// the symbolic name used for the message Id. Useful for debugging\n"
|
|
"// output.\n"
|
|
"//\n\n"
|
|
"struct {\n",
|
|
DebugFile );
|
|
|
|
fprintf(
|
|
DebugFile,
|
|
" %ws MessageId;\n"
|
|
" char *SymbolicName;\n"
|
|
"} %sSymbolicNames[] = {\n",
|
|
wszMessageType,
|
|
MessageFileNameNoExt );
|
|
}
|
|
}
|
|
|
|
if (!McParseMessageDefinition()) {
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
McInputErrorW( L"Invalid message file token - '%s'", TRUE, TokenCharValue );
|
|
return( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (GenerateDebugFile) {
|
|
fprintf( DebugFile, " (%ws) 0xFFFFFFFF, NULL\n};\n", wszMessageType );
|
|
}
|
|
|
|
McFlushComments();
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOL
|
|
McParseMessageDefinition( void )
|
|
{
|
|
unsigned int t;
|
|
PMESSAGE_INFO MessageInfo;
|
|
BOOL MessageIdSeen;
|
|
PMESSAGE_INFO MessageInfoTemp, *pp;
|
|
|
|
McFlushComments();
|
|
|
|
MessageInfo = malloc( sizeof( *MessageInfo ) );
|
|
if (!MessageInfo) {
|
|
McInputErrorA( "Out of memory parsing memory definitions.", TRUE, NULL );
|
|
return( FALSE );
|
|
}
|
|
MessageInfo->Next = NULL;
|
|
MessageInfo->Id = 0;
|
|
MessageInfo->Method = MSG_PLUS_ONE;
|
|
MessageInfo->SymbolicName = NULL;
|
|
MessageInfo->EndOfLineComment = NULL;
|
|
MessageInfo->MessageText = NULL;
|
|
MessageIdSeen = FALSE;
|
|
|
|
while ((t = McGetToken( TRUE )) != MCTOK_END_OF_FILE) {
|
|
switch (t) {
|
|
case MCTOK_MESSAGEID_KEYWORD:
|
|
if (MessageIdSeen) {
|
|
McInputErrorA( "Invalid message definition - text missing.", TRUE, NULL );
|
|
return( FALSE );
|
|
}
|
|
|
|
MessageIdSeen = TRUE;
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
|
|
MessageInfo->Id = TokenNumericValue;
|
|
MessageInfo->Method = MSG_ABSOLUTE;
|
|
} else
|
|
if (t == MCTOK_PLUS) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
|
|
MessageInfo->Id = TokenNumericValue;
|
|
MessageInfo->Method = MSG_PLUS_VALUE;
|
|
} else {
|
|
McInputErrorW( L"Number must follow %s=+", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McUnGetToken();
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
case MCTOK_SEVERITY_KEYWORD:
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if (!McParseName( SeverityNames, &CurrentSeverityName )) {
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
case MCTOK_FACILITY_KEYWORD:
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if (!McParseName( FacilityNames, &CurrentFacilityName )) {
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
case MCTOK_SYMBOLNAME_KEYWORD:
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
|
|
MessageInfo->SymbolicName = McMakeString( TokenCharValue );
|
|
} else {
|
|
McInputErrorW( L"Symbol name must follow %s=+", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
break;
|
|
|
|
|
|
case MCTOK_END_OF_LINE_COMMENT:
|
|
MessageInfo->EndOfLineComment = McMakeString( TokenCharValue );
|
|
break;
|
|
|
|
case MCTOK_LANGUAGE_KEYWORD:
|
|
McUnGetToken();
|
|
|
|
|
|
if (MessageInfo->Method == MSG_PLUS_ONE) {
|
|
MessageInfo->Id = CurrentFacilityName->LastId + 1;
|
|
} else
|
|
if (MessageInfo->Method == MSG_PLUS_VALUE) {
|
|
MessageInfo->Id = CurrentFacilityName->LastId + MessageInfo->Id;
|
|
}
|
|
|
|
if (MessageInfo->Id > 0xFFFFL) {
|
|
McInputErrorA( "Message Id value (%lx) too large", TRUE, (PVOID)UlongToPtr(MessageInfo->Id) );
|
|
return( FALSE );
|
|
}
|
|
|
|
MessageInfo->Id |= (CurrentSeverityName->Id << 30) |
|
|
CustomerMsgIdBit |
|
|
(CurrentFacilityName->Id << 16);
|
|
|
|
fprintf( HeaderFile, "//\r\n" );
|
|
if (MessageInfo->SymbolicName) {
|
|
fprintf( HeaderFile, "// MessageId: %ws\r\n",
|
|
MessageInfo->SymbolicName
|
|
);
|
|
} else {
|
|
fprintf( HeaderFile, "// MessageId: 0x%08lXL (No symbolic name defined)\r\n",
|
|
MessageInfo->Id
|
|
);
|
|
}
|
|
|
|
fprintf( HeaderFile, "//\r\n" );
|
|
fprintf( HeaderFile, "// MessageText:\r\n" );
|
|
fprintf( HeaderFile, "//\r\n" );
|
|
|
|
if (McParseMessageText( MessageInfo )) {
|
|
fprintf( HeaderFile, "//\r\n" );
|
|
if (MessageInfo->SymbolicName) {
|
|
if (GenerateDebugFile) {
|
|
fprintf( DebugFile, " (%ws) %ws, \"%ws\",\n",
|
|
wszMessageType,
|
|
MessageInfo->SymbolicName,
|
|
MessageInfo->SymbolicName
|
|
);
|
|
}
|
|
|
|
if (MessageIdTypeMacro != NULL) {
|
|
fprintf( HeaderFile, GenerateDecimalMessageValues ?
|
|
"#define %-32ws %ws(%ldL)" :
|
|
"#define %-32ws %ws(0x%08lXL)",
|
|
MessageInfo->SymbolicName,
|
|
MessageIdTypeMacro,
|
|
MessageInfo->Id
|
|
);
|
|
} else {
|
|
if (MessageIdTypeName != NULL) {
|
|
fprintf( HeaderFile, GenerateDecimalMessageValues ?
|
|
"#define %-32ws ((%ws)%ldL)" :
|
|
"#define %-32ws ((%ws)0x%08lXL)",
|
|
MessageInfo->SymbolicName,
|
|
wszMessageType,
|
|
MessageInfo->Id
|
|
);
|
|
} else {
|
|
fprintf( HeaderFile, GenerateDecimalMessageValues ?
|
|
"#define %-32ws %ldL" :
|
|
"#define %-32ws 0x%08lXL",
|
|
MessageInfo->SymbolicName,
|
|
MessageInfo->Id
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (MessageInfo->EndOfLineComment) {
|
|
fprintf( HeaderFile, " %ws", MessageInfo->EndOfLineComment );
|
|
} else {
|
|
fprintf( HeaderFile, "\r\n" );
|
|
}
|
|
fprintf( HeaderFile, "\r\n" );
|
|
|
|
//
|
|
// Scan the existing messages to see if this message
|
|
// exists in the message file.
|
|
//
|
|
// If it does, generate and error for the user. Otherwise
|
|
// insert new message in list in ascending Id order.
|
|
//
|
|
|
|
pp = &Messages;
|
|
while (MessageInfoTemp = *pp) {
|
|
if (MessageInfoTemp->Id == MessageInfo->Id) {
|
|
if (MessageInfo->SymbolicName && MessageInfoTemp->SymbolicName) {
|
|
fprintf( stderr,
|
|
"%s(%d) : error : Duplicate message ID - 0x%x (%ws and %ws)\n",
|
|
MessageFileName,
|
|
MessageFileLineNumber,
|
|
MessageInfo->Id,
|
|
MessageInfoTemp->SymbolicName,
|
|
MessageInfo->SymbolicName
|
|
);
|
|
} else {
|
|
McInputErrorA( "Duplicate message ID - 0x%lx", TRUE, (PVOID)UlongToPtr(MessageInfo->Id) );
|
|
}
|
|
} else {
|
|
if (MessageInfoTemp->Id > MessageInfo->Id) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
pp = &MessageInfoTemp->Next;
|
|
}
|
|
|
|
MessageInfo->Next = *pp;
|
|
*pp = MessageInfo;
|
|
|
|
CurrentMessage = MessageInfo;
|
|
CurrentFacilityName->LastId = MessageInfo->Id & 0xFFFF;
|
|
return( TRUE );
|
|
} else {
|
|
return( FALSE );
|
|
}
|
|
|
|
default:
|
|
McInputErrorW( L"Invalid message definition token - '%s'", TRUE, TokenCharValue );
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
WCHAR MessageTextBuffer[ 32767 ];
|
|
|
|
BOOL
|
|
McParseMessageText(
|
|
PMESSAGE_INFO MessageInfo
|
|
)
|
|
{
|
|
PLANGUAGE_INFO MessageText, *pp;
|
|
WCHAR *src, *dst;
|
|
unsigned int t, n;
|
|
BOOL FirstLanguageProcessed;
|
|
|
|
pp = &MessageInfo->MessageText;
|
|
|
|
FirstLanguageProcessed = FALSE;
|
|
while ((t = McGetToken( TRUE )) != MCTOK_END_OF_FILE) {
|
|
if (t == MCTOK_LANGUAGE_KEYWORD) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if (!McParseName( LanguageNames, &CurrentLanguageName )) {
|
|
return( FALSE );
|
|
}
|
|
GetCPInfo(CurrentLanguageName->CodePage, &CPInfo);
|
|
} else {
|
|
McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McUnGetToken();
|
|
break;
|
|
}
|
|
|
|
MessageText = malloc( sizeof( *MessageText ) );
|
|
MessageText->Next = NULL;
|
|
MessageText->Id = CurrentLanguageName->Id;
|
|
MessageText->Length = 0;
|
|
MessageText->Text = NULL;
|
|
|
|
dst = MessageTextBuffer;
|
|
*MessageTextBuffer = L'\0';
|
|
while (src = McGetLine()) {
|
|
n = wcslen( MessageTextBuffer );
|
|
// If the message buffer is complete, see if this is a '.' record.
|
|
if (((n == 0) || *(MessageTextBuffer+n-1) == L'\n') &&
|
|
!wcscmp( src, L".\r\n" )) {
|
|
if (MessageText->Length == 0) {
|
|
if (MessageInfo->SymbolicName) {
|
|
wcscpy( dst, MessageInfo->SymbolicName );
|
|
} else {
|
|
swprintf( dst, L"No symbolic name defined for0x%08lXL" );
|
|
}
|
|
|
|
wcscat( dst, L"\r\n" );
|
|
if (!FirstLanguageProcessed) {
|
|
fprintf( HeaderFile, "// %ws", dst );
|
|
}
|
|
|
|
n = wcslen( dst );
|
|
dst += n;
|
|
MessageText->Length += n;
|
|
}
|
|
|
|
McSkipLine();
|
|
break;
|
|
}
|
|
else if (!_wcsnicmp( src, L"LanguageId=", 11 ) ||
|
|
!_wcsnicmp( src, L"MessageId=", 10 )) {
|
|
McInputErrorA( "Unterminated message definition", TRUE, NULL );
|
|
return( FALSE );
|
|
}
|
|
|
|
if (!FirstLanguageProcessed) {
|
|
// To write DBCS comments to the header file.
|
|
//
|
|
// fprintf() does not work correctly with Unicode
|
|
// to write DBCS characters. Convert Unicode to
|
|
// MultiByte and use the Ansi string instead...
|
|
char * pch;
|
|
|
|
int len = WideCharToMultiByte(CurrentLanguageName->CodePage,
|
|
0, // No flags
|
|
src, // The buffer to convert
|
|
-1, // It's zero terminated
|
|
NULL,
|
|
0, // Tell us how much to allocate
|
|
NULL, // No default char
|
|
NULL); // No used default char
|
|
|
|
pch = malloc(len + 1);
|
|
|
|
WideCharToMultiByte(CurrentLanguageName->CodePage,
|
|
0,
|
|
src,
|
|
-1,
|
|
pch, // The buffer to fill in
|
|
len, // How big it is
|
|
NULL,
|
|
NULL);
|
|
|
|
fprintf( HeaderFile, "// %s", pch );
|
|
free(pch);
|
|
}
|
|
|
|
n = wcslen( src );
|
|
if (MessageText->Length + n > sizeof( MessageTextBuffer )) {
|
|
McInputErrorA( "Message text too long (> %ld)", TRUE,
|
|
(PVOID)UlongToPtr((ULONG)sizeof( MessageTextBuffer ))
|
|
);
|
|
return( FALSE );
|
|
}
|
|
|
|
wcscpy( dst, src );
|
|
dst += n;
|
|
MessageText->Length += n;
|
|
|
|
if (MaxMessageLength != 0 && (MessageText->Length > (ULONG)MaxMessageLength)) {
|
|
McInputErrorA( "Message text larger than size specified by -m %d",
|
|
TRUE,
|
|
(PVOID)IntToPtr(MaxMessageLength)
|
|
);
|
|
}
|
|
}
|
|
*dst = L'\0';
|
|
|
|
// Add NULL terminator if requested
|
|
if (NULLTerminate)
|
|
{
|
|
MessageText->Length -= 2;
|
|
MessageTextBuffer[MessageText->Length] = L'\0';
|
|
}
|
|
n = (((USHORT)MessageText->Length) + 1) * sizeof( WCHAR );
|
|
MessageText->Text = malloc( n );
|
|
memcpy( MessageText->Text, MessageTextBuffer, n );
|
|
if (UnicodeOutput)
|
|
MessageText->Length = n - sizeof( WCHAR );
|
|
else
|
|
MessageText->Length = WideCharToMultiByte(
|
|
CurrentLanguageName->CodePage,
|
|
0, MessageTextBuffer, MessageText->Length,
|
|
NULL, 0, NULL, NULL );
|
|
*pp = MessageText;
|
|
pp = &MessageText->Next;
|
|
FirstLanguageProcessed = TRUE;
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOL
|
|
McParseNameList(
|
|
PNAME_INFO *NameListHead,
|
|
BOOL ValueRequired,
|
|
ULONG MaximumValue
|
|
)
|
|
{
|
|
unsigned int t;
|
|
PNAME_INFO p = NULL;
|
|
WCHAR *Name;
|
|
ULONG Id;
|
|
PVOID Value;
|
|
|
|
Name = NULL;
|
|
Id = 0;
|
|
|
|
while ((t = McGetToken( FALSE )) != MCTOK_END_OF_FILE) {
|
|
if (t == MCTOK_RIGHT_PAREN) {
|
|
return( TRUE );
|
|
}
|
|
|
|
if (t == MCTOK_NAME) {
|
|
Name = McMakeString( TokenCharValue );
|
|
Id = 0;
|
|
Value = NULL;
|
|
if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
|
|
Id = TokenNumericValue;
|
|
if ((t = McGetToken( FALSE )) == MCTOK_COLON) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
|
|
Value = McMakeString( TokenCharValue );
|
|
} else {
|
|
McInputErrorA( "File name must follow =%ld:", TRUE, (PVOID)UlongToPtr(Id) );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
if (ValueRequired) {
|
|
McInputErrorA( "Colon must follow =%ld", TRUE, (PVOID)UlongToPtr(Id) );
|
|
return( FALSE );
|
|
}
|
|
|
|
McUnGetToken();
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Number must follow %s=", TRUE, Name );
|
|
return( FALSE );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Equal sign name must follow %s", TRUE, Name );
|
|
return( FALSE );
|
|
}
|
|
|
|
if (Id > MaximumValue) {
|
|
McInputErrorA( "Value is too large (> %lx)", TRUE, (PVOID)UlongToPtr(MaximumValue) );
|
|
return( FALSE );
|
|
}
|
|
|
|
p = McAddName( NameListHead, Name, Id, Value );
|
|
free( Name );
|
|
}
|
|
else if (t == MCTOK_COLON && p) {
|
|
if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
|
|
p->CodePage = (USHORT)TokenNumericValue;
|
|
if (!IsValidCodePage(TokenNumericValue)) {
|
|
McInputErrorW( L"CodePage %d is invalid", TRUE, (PVOID)UlongToPtr(TokenNumericValue) );
|
|
return( FALSE );
|
|
}
|
|
if (VerboseOutput) {
|
|
fprintf( stderr, "Using CodePage %d for Language %04x\n", TokenNumericValue, Id);
|
|
}
|
|
} else {
|
|
McInputErrorW( L"CodePage must follow %s=:", TRUE, Name );
|
|
return( FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOL
|
|
McParseName(
|
|
PNAME_INFO NameListHead,
|
|
PNAME_INFO *Result
|
|
)
|
|
{
|
|
unsigned int t;
|
|
PNAME_INFO p;
|
|
|
|
if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
|
|
p = McFindName( NameListHead, TokenCharValue );
|
|
if (p != NULL) {
|
|
*Result = p;
|
|
return( TRUE );
|
|
} else {
|
|
McInputErrorW( L"Invalid name - %s", TRUE, TokenCharValue );
|
|
}
|
|
} else {
|
|
McInputErrorW( L"Missing name after %s=", TRUE, TokenKeyword->Name );
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|