Source code of Windows XP (NT5)
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.

771 lines
29 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. mcparse.c
  5. Abstract:
  6. This file contains the parse logic for the Win32 Message Compiler (MC)
  7. Author:
  8. Steve Wood (stevewo) 22-Aug-1991
  9. Revision History:
  10. --*/
  11. #include "mc.h"
  12. WCHAR * wszMessageType = L"DWORD"; // Init to a known state
  13. BOOL
  14. McParseFile( void )
  15. {
  16. unsigned int t;
  17. BOOL FirstMessageDefinition = TRUE;
  18. PNAME_INFO p;
  19. if (!McOpenInputFile()) {
  20. fprintf( stderr, "MC: Unable to open %s for input\n", MessageFileName );
  21. return( FALSE );
  22. }
  23. fprintf( stderr, "MC: Compiling %s\n", MessageFileName );
  24. while ((t = McGetToken( TRUE )) != MCTOK_END_OF_FILE) {
  25. switch (t) {
  26. case MCTOK_MSGIDTYPE_KEYWORD:
  27. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  28. if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  29. wszMessageType = MessageIdTypeName = McMakeString( TokenCharValue );
  30. } else {
  31. McInputErrorW( L"Symbol name must follow %s=", TRUE, TokenKeyword->Name );
  32. return( FALSE );
  33. }
  34. } else {
  35. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  36. return( FALSE );
  37. }
  38. break;
  39. case MCTOK_MSGTYPEDEF_KEYWORD:
  40. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  41. if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  42. MessageIdTypeMacro = McMakeString( TokenCharValue );
  43. } else {
  44. McInputErrorW( L"Symbol name must follow %s=", TRUE, TokenKeyword->Name );
  45. return( FALSE );
  46. }
  47. } else {
  48. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  49. return( FALSE );
  50. }
  51. break;
  52. case MCTOK_OUTBASE_KEYWORD:
  53. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  54. if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  55. if (TokenNumericValue == 16) {
  56. GenerateDecimalMessageValues = FALSE;
  57. } else if (TokenNumericValue == 10) {
  58. GenerateDecimalMessageValues = TRUE;
  59. } else {
  60. McInputErrorW( L"Illegal value for %s=", TRUE, TokenKeyword->Name );
  61. }
  62. } else {
  63. McInputErrorW( L"Number must follow %s=", TRUE, TokenKeyword->Name );
  64. return( FALSE );
  65. }
  66. } else {
  67. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  68. return( FALSE );
  69. }
  70. break;
  71. case MCTOK_SEVNAMES_KEYWORD:
  72. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  73. if ((t = McGetToken( FALSE )) == MCTOK_LEFT_PAREN) {
  74. if (!McParseNameList( &SeverityNames, FALSE, 0x3L )) {
  75. return( FALSE );
  76. }
  77. } else {
  78. McInputErrorW( L"Left parenthesis name must follow %s=", TRUE, TokenKeyword->Name );
  79. return( FALSE );
  80. }
  81. } else {
  82. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  83. return( FALSE );
  84. }
  85. break;
  86. case MCTOK_FACILITYNAMES_KEYWORD:
  87. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  88. if ((t = McGetToken( FALSE )) == MCTOK_LEFT_PAREN) {
  89. if (!McParseNameList( &FacilityNames, FALSE, 0xFFFL )) {
  90. return( FALSE );
  91. }
  92. } else {
  93. McInputErrorW( L"Left parenthesis name must follow %s=", TRUE, TokenKeyword->Name );
  94. return( FALSE );
  95. }
  96. } else {
  97. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  98. return( FALSE );
  99. }
  100. break;
  101. case MCTOK_LANGNAMES_KEYWORD:
  102. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  103. if ((t = McGetToken( FALSE )) == MCTOK_LEFT_PAREN) {
  104. if (!McParseNameList( &LanguageNames, TRUE, 0xFFFFL )) {
  105. return( FALSE );
  106. }
  107. } else {
  108. McInputErrorW( L"Left parenthesis name must follow %s=", TRUE, TokenKeyword->Name );
  109. return( FALSE );
  110. }
  111. } else {
  112. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  113. return( FALSE );
  114. }
  115. break;
  116. case MCTOK_MESSAGEID_KEYWORD:
  117. McUnGetToken();
  118. if (FirstMessageDefinition) {
  119. FirstMessageDefinition = FALSE;
  120. McFlushComments();
  121. if (OleOutput) {
  122. fputs(
  123. "//\r\n"
  124. "// Values are 32 bit values layed out as follows:\r\n"
  125. "//\r\n"
  126. "// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1\r\n"
  127. "// 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"
  128. "// +-+-+-+-+-+---------------------+-------------------------------+\r\n"
  129. "// |S|R|C|N|r| Facility | Code |\r\n"
  130. "// +-+-+-+-+-+---------------------+-------------------------------+\r\n"
  131. "//\r\n"
  132. "// where\r\n"
  133. "//\r\n"
  134. "// S - Severity - indicates success/fail\r\n"
  135. "//\r\n"
  136. "// 0 - Success\r\n"
  137. "// 1 - Fail (COERROR)\r\n"
  138. "//\r\n"
  139. "// R - reserved portion of the facility code, corresponds to NT's\r\n"
  140. "// second severity bit.\r\n"
  141. "//\r\n"
  142. "// C - reserved portion of the facility code, corresponds to NT's\r\n"
  143. "// C field.\r\n"
  144. "//\r\n"
  145. "// N - reserved portion of the facility code. Used to indicate a\r\n"
  146. "// mapped NT status value.\r\n"
  147. "//\r\n"
  148. "// r - reserved portion of the facility code. Reserved for internal\r\n"
  149. "// use. Used to indicate HRESULT values that are not status\r\n"
  150. "// values, but are instead message ids for display strings.\r\n"
  151. "//\r\n"
  152. "// Facility - is the facility code\r\n"
  153. "//\r\n"
  154. "// Code - is the facility's status code\r\n"
  155. "//\r\n",
  156. HeaderFile );
  157. } else {
  158. fputs(
  159. "//\r\n"
  160. "// Values are 32 bit values layed out as follows:\r\n"
  161. "//\r\n"
  162. "// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1\r\n"
  163. "// 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"
  164. "// +---+-+-+-----------------------+-------------------------------+\r\n"
  165. "// |Sev|C|R| Facility | Code |\r\n"
  166. "// +---+-+-+-----------------------+-------------------------------+\r\n"
  167. "//\r\n"
  168. "// where\r\n"
  169. "//\r\n"
  170. "// Sev - is the severity code\r\n"
  171. "//\r\n"
  172. "// 00 - Success\r\n"
  173. "// 01 - Informational\r\n"
  174. "// 10 - Warning\r\n"
  175. "// 11 - Error\r\n"
  176. "//\r\n"
  177. "// C - is the Customer code flag\r\n"
  178. "//\r\n"
  179. "// R - is a reserved bit\r\n"
  180. "//\r\n"
  181. "// Facility - is the facility code\r\n"
  182. "//\r\n"
  183. "// Code - is the facility's status code\r\n"
  184. "//\r\n",
  185. HeaderFile );
  186. }
  187. fputs(
  188. "//\r\n"
  189. "// Define the facility codes\r\n"
  190. "//\r\n",
  191. HeaderFile );
  192. p = FacilityNames;
  193. while( p ) {
  194. if (p->Value) {
  195. fprintf( HeaderFile, GenerateDecimalSevAndFacValues ?
  196. "#define %-32ws %ld\r\n" :
  197. "#define %-32ws 0x%lX\r\n",
  198. p->Value, p->Id
  199. );
  200. }
  201. p = p->Next;
  202. }
  203. fputs(
  204. "\r\n"
  205. "\r\n"
  206. "//\r\n"
  207. "// Define the severity codes\r\n"
  208. "//\r\n",
  209. HeaderFile );
  210. p = SeverityNames;
  211. while( p ) {
  212. if (p->Value) {
  213. fprintf( HeaderFile, GenerateDecimalSevAndFacValues ?
  214. "#define %-32ws %ld\r\n" :
  215. "#define %-32ws 0x%lX\r\n",
  216. p->Value, p->Id
  217. );
  218. }
  219. p = p->Next;
  220. }
  221. fputs(
  222. "\r\n"
  223. "\r\n",
  224. HeaderFile );
  225. if (GenerateDebugFile) {
  226. fputs(
  227. "//\n"
  228. "// This file maps message Id values in to a text string that contains\n"
  229. "// the symbolic name used for the message Id. Useful for debugging\n"
  230. "// output.\n"
  231. "//\n\n"
  232. "struct {\n",
  233. DebugFile );
  234. fprintf(
  235. DebugFile,
  236. " %ws MessageId;\n"
  237. " char *SymbolicName;\n"
  238. "} %sSymbolicNames[] = {\n",
  239. wszMessageType,
  240. MessageFileNameNoExt );
  241. }
  242. }
  243. if (!McParseMessageDefinition()) {
  244. return( FALSE );
  245. }
  246. break;
  247. default:
  248. McInputErrorW( L"Invalid message file token - '%s'", TRUE, TokenCharValue );
  249. return( FALSE );
  250. break;
  251. }
  252. }
  253. if (GenerateDebugFile) {
  254. fprintf( DebugFile, " (%ws) 0xFFFFFFFF, NULL\n};\n", wszMessageType );
  255. }
  256. McFlushComments();
  257. return( TRUE );
  258. }
  259. BOOL
  260. McParseMessageDefinition( void )
  261. {
  262. unsigned int t;
  263. PMESSAGE_INFO MessageInfo;
  264. BOOL MessageIdSeen;
  265. PMESSAGE_INFO MessageInfoTemp, *pp;
  266. McFlushComments();
  267. MessageInfo = malloc( sizeof( *MessageInfo ) );
  268. if (!MessageInfo) {
  269. McInputErrorA( "Out of memory parsing memory definitions.", TRUE, NULL );
  270. return( FALSE );
  271. }
  272. MessageInfo->Next = NULL;
  273. MessageInfo->Id = 0;
  274. MessageInfo->Method = MSG_PLUS_ONE;
  275. MessageInfo->SymbolicName = NULL;
  276. MessageInfo->EndOfLineComment = NULL;
  277. MessageInfo->MessageText = NULL;
  278. MessageIdSeen = FALSE;
  279. while ((t = McGetToken( TRUE )) != MCTOK_END_OF_FILE) {
  280. switch (t) {
  281. case MCTOK_MESSAGEID_KEYWORD:
  282. if (MessageIdSeen) {
  283. McInputErrorA( "Invalid message definition - text missing.", TRUE, NULL );
  284. return( FALSE );
  285. }
  286. MessageIdSeen = TRUE;
  287. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  288. if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  289. MessageInfo->Id = TokenNumericValue;
  290. MessageInfo->Method = MSG_ABSOLUTE;
  291. } else
  292. if (t == MCTOK_PLUS) {
  293. if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  294. MessageInfo->Id = TokenNumericValue;
  295. MessageInfo->Method = MSG_PLUS_VALUE;
  296. } else {
  297. McInputErrorW( L"Number must follow %s=+", TRUE, TokenKeyword->Name );
  298. return( FALSE );
  299. }
  300. } else {
  301. McUnGetToken();
  302. }
  303. } else {
  304. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  305. return( FALSE );
  306. }
  307. break;
  308. case MCTOK_SEVERITY_KEYWORD:
  309. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  310. if (!McParseName( SeverityNames, &CurrentSeverityName )) {
  311. return( FALSE );
  312. }
  313. } else {
  314. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  315. return( FALSE );
  316. }
  317. break;
  318. case MCTOK_FACILITY_KEYWORD:
  319. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  320. if (!McParseName( FacilityNames, &CurrentFacilityName )) {
  321. return( FALSE );
  322. }
  323. } else {
  324. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  325. return( FALSE );
  326. }
  327. break;
  328. case MCTOK_SYMBOLNAME_KEYWORD:
  329. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  330. if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  331. MessageInfo->SymbolicName = McMakeString( TokenCharValue );
  332. } else {
  333. McInputErrorW( L"Symbol name must follow %s=+", TRUE, TokenKeyword->Name );
  334. return( FALSE );
  335. }
  336. } else {
  337. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  338. return( FALSE );
  339. }
  340. break;
  341. case MCTOK_END_OF_LINE_COMMENT:
  342. MessageInfo->EndOfLineComment = McMakeString( TokenCharValue );
  343. break;
  344. case MCTOK_LANGUAGE_KEYWORD:
  345. McUnGetToken();
  346. if (MessageInfo->Method == MSG_PLUS_ONE) {
  347. MessageInfo->Id = CurrentFacilityName->LastId + 1;
  348. } else
  349. if (MessageInfo->Method == MSG_PLUS_VALUE) {
  350. MessageInfo->Id = CurrentFacilityName->LastId + MessageInfo->Id;
  351. }
  352. if (MessageInfo->Id > 0xFFFFL) {
  353. McInputErrorA( "Message Id value (%lx) too large", TRUE, (PVOID)UlongToPtr(MessageInfo->Id) );
  354. return( FALSE );
  355. }
  356. MessageInfo->Id |= (CurrentSeverityName->Id << 30) |
  357. CustomerMsgIdBit |
  358. (CurrentFacilityName->Id << 16);
  359. fprintf( HeaderFile, "//\r\n" );
  360. if (MessageInfo->SymbolicName) {
  361. fprintf( HeaderFile, "// MessageId: %ws\r\n",
  362. MessageInfo->SymbolicName
  363. );
  364. } else {
  365. fprintf( HeaderFile, "// MessageId: 0x%08lXL (No symbolic name defined)\r\n",
  366. MessageInfo->Id
  367. );
  368. }
  369. fprintf( HeaderFile, "//\r\n" );
  370. fprintf( HeaderFile, "// MessageText:\r\n" );
  371. fprintf( HeaderFile, "//\r\n" );
  372. if (McParseMessageText( MessageInfo )) {
  373. fprintf( HeaderFile, "//\r\n" );
  374. if (MessageInfo->SymbolicName) {
  375. if (GenerateDebugFile) {
  376. fprintf( DebugFile, " (%ws) %ws, \"%ws\",\n",
  377. wszMessageType,
  378. MessageInfo->SymbolicName,
  379. MessageInfo->SymbolicName
  380. );
  381. }
  382. if (MessageIdTypeMacro != NULL) {
  383. fprintf( HeaderFile, GenerateDecimalMessageValues ?
  384. "#define %-32ws %ws(%ldL)" :
  385. "#define %-32ws %ws(0x%08lXL)",
  386. MessageInfo->SymbolicName,
  387. MessageIdTypeMacro,
  388. MessageInfo->Id
  389. );
  390. } else {
  391. if (MessageIdTypeName != NULL) {
  392. fprintf( HeaderFile, GenerateDecimalMessageValues ?
  393. "#define %-32ws ((%ws)%ldL)" :
  394. "#define %-32ws ((%ws)0x%08lXL)",
  395. MessageInfo->SymbolicName,
  396. wszMessageType,
  397. MessageInfo->Id
  398. );
  399. } else {
  400. fprintf( HeaderFile, GenerateDecimalMessageValues ?
  401. "#define %-32ws %ldL" :
  402. "#define %-32ws 0x%08lXL",
  403. MessageInfo->SymbolicName,
  404. MessageInfo->Id
  405. );
  406. }
  407. }
  408. }
  409. if (MessageInfo->EndOfLineComment) {
  410. fprintf( HeaderFile, " %ws", MessageInfo->EndOfLineComment );
  411. } else {
  412. fprintf( HeaderFile, "\r\n" );
  413. }
  414. fprintf( HeaderFile, "\r\n" );
  415. //
  416. // Scan the existing messages to see if this message
  417. // exists in the message file.
  418. //
  419. // If it does, generate and error for the user. Otherwise
  420. // insert new message in list in ascending Id order.
  421. //
  422. pp = &Messages;
  423. while (MessageInfoTemp = *pp) {
  424. if (MessageInfoTemp->Id == MessageInfo->Id) {
  425. if (MessageInfo->SymbolicName && MessageInfoTemp->SymbolicName) {
  426. fprintf( stderr,
  427. "%s(%d) : error : Duplicate message ID - 0x%x (%ws and %ws)\n",
  428. MessageFileName,
  429. MessageFileLineNumber,
  430. MessageInfo->Id,
  431. MessageInfoTemp->SymbolicName,
  432. MessageInfo->SymbolicName
  433. );
  434. } else {
  435. McInputErrorA( "Duplicate message ID - 0x%lx", TRUE, (PVOID)UlongToPtr(MessageInfo->Id) );
  436. }
  437. } else {
  438. if (MessageInfoTemp->Id > MessageInfo->Id) {
  439. break;
  440. }
  441. }
  442. pp = &MessageInfoTemp->Next;
  443. }
  444. MessageInfo->Next = *pp;
  445. *pp = MessageInfo;
  446. CurrentMessage = MessageInfo;
  447. CurrentFacilityName->LastId = MessageInfo->Id & 0xFFFF;
  448. return( TRUE );
  449. } else {
  450. return( FALSE );
  451. }
  452. default:
  453. McInputErrorW( L"Invalid message definition token - '%s'", TRUE, TokenCharValue );
  454. return( FALSE );
  455. }
  456. }
  457. return( FALSE );
  458. }
  459. WCHAR MessageTextBuffer[ 32767 ];
  460. BOOL
  461. McParseMessageText(
  462. PMESSAGE_INFO MessageInfo
  463. )
  464. {
  465. PLANGUAGE_INFO MessageText, *pp;
  466. WCHAR *src, *dst;
  467. unsigned int t, n;
  468. BOOL FirstLanguageProcessed;
  469. pp = &MessageInfo->MessageText;
  470. FirstLanguageProcessed = FALSE;
  471. while ((t = McGetToken( TRUE )) != MCTOK_END_OF_FILE) {
  472. if (t == MCTOK_LANGUAGE_KEYWORD) {
  473. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  474. if (!McParseName( LanguageNames, &CurrentLanguageName )) {
  475. return( FALSE );
  476. }
  477. GetCPInfo(CurrentLanguageName->CodePage, &CPInfo);
  478. } else {
  479. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  480. return( FALSE );
  481. }
  482. } else {
  483. McUnGetToken();
  484. break;
  485. }
  486. MessageText = malloc( sizeof( *MessageText ) );
  487. MessageText->Next = NULL;
  488. MessageText->Id = CurrentLanguageName->Id;
  489. MessageText->Length = 0;
  490. MessageText->Text = NULL;
  491. dst = MessageTextBuffer;
  492. *MessageTextBuffer = L'\0';
  493. while (src = McGetLine()) {
  494. n = wcslen( MessageTextBuffer );
  495. // If the message buffer is complete, see if this is a '.' record.
  496. if (((n == 0) || *(MessageTextBuffer+n-1) == L'\n') &&
  497. !wcscmp( src, L".\r\n" )) {
  498. if (MessageText->Length == 0) {
  499. if (MessageInfo->SymbolicName) {
  500. wcscpy( dst, MessageInfo->SymbolicName );
  501. } else {
  502. swprintf( dst, L"No symbolic name defined for0x%08lXL" );
  503. }
  504. wcscat( dst, L"\r\n" );
  505. if (!FirstLanguageProcessed) {
  506. fprintf( HeaderFile, "// %ws", dst );
  507. }
  508. n = wcslen( dst );
  509. dst += n;
  510. MessageText->Length += n;
  511. }
  512. McSkipLine();
  513. break;
  514. }
  515. else if (!_wcsnicmp( src, L"LanguageId=", 11 ) ||
  516. !_wcsnicmp( src, L"MessageId=", 10 )) {
  517. McInputErrorA( "Unterminated message definition", TRUE, NULL );
  518. return( FALSE );
  519. }
  520. if (!FirstLanguageProcessed) {
  521. // To write DBCS comments to the header file.
  522. //
  523. // fprintf() does not work correctly with Unicode
  524. // to write DBCS characters. Convert Unicode to
  525. // MultiByte and use the Ansi string instead...
  526. char * pch;
  527. int len = WideCharToMultiByte(CurrentLanguageName->CodePage,
  528. 0, // No flags
  529. src, // The buffer to convert
  530. -1, // It's zero terminated
  531. NULL,
  532. 0, // Tell us how much to allocate
  533. NULL, // No default char
  534. NULL); // No used default char
  535. pch = malloc(len + 1);
  536. WideCharToMultiByte(CurrentLanguageName->CodePage,
  537. 0,
  538. src,
  539. -1,
  540. pch, // The buffer to fill in
  541. len, // How big it is
  542. NULL,
  543. NULL);
  544. fprintf( HeaderFile, "// %s", pch );
  545. free(pch);
  546. }
  547. n = wcslen( src );
  548. if (MessageText->Length + n > sizeof( MessageTextBuffer )) {
  549. McInputErrorA( "Message text too long (> %ld)", TRUE,
  550. (PVOID)UlongToPtr((ULONG)sizeof( MessageTextBuffer ))
  551. );
  552. return( FALSE );
  553. }
  554. wcscpy( dst, src );
  555. dst += n;
  556. MessageText->Length += n;
  557. if (MaxMessageLength != 0 && (MessageText->Length > (ULONG)MaxMessageLength)) {
  558. McInputErrorA( "Message text larger than size specified by -m %d",
  559. TRUE,
  560. (PVOID)IntToPtr(MaxMessageLength)
  561. );
  562. }
  563. }
  564. *dst = L'\0';
  565. // Add NULL terminator if requested
  566. if (NULLTerminate)
  567. {
  568. MessageText->Length -= 2;
  569. MessageTextBuffer[MessageText->Length] = L'\0';
  570. }
  571. n = (((USHORT)MessageText->Length) + 1) * sizeof( WCHAR );
  572. MessageText->Text = malloc( n );
  573. memcpy( MessageText->Text, MessageTextBuffer, n );
  574. if (UnicodeOutput)
  575. MessageText->Length = n - sizeof( WCHAR );
  576. else
  577. MessageText->Length = WideCharToMultiByte(
  578. CurrentLanguageName->CodePage,
  579. 0, MessageTextBuffer, MessageText->Length,
  580. NULL, 0, NULL, NULL );
  581. *pp = MessageText;
  582. pp = &MessageText->Next;
  583. FirstLanguageProcessed = TRUE;
  584. }
  585. return( TRUE );
  586. }
  587. BOOL
  588. McParseNameList(
  589. PNAME_INFO *NameListHead,
  590. BOOL ValueRequired,
  591. ULONG MaximumValue
  592. )
  593. {
  594. unsigned int t;
  595. PNAME_INFO p = NULL;
  596. WCHAR *Name;
  597. ULONG Id;
  598. PVOID Value;
  599. Name = NULL;
  600. Id = 0;
  601. while ((t = McGetToken( FALSE )) != MCTOK_END_OF_FILE) {
  602. if (t == MCTOK_RIGHT_PAREN) {
  603. return( TRUE );
  604. }
  605. if (t == MCTOK_NAME) {
  606. Name = McMakeString( TokenCharValue );
  607. Id = 0;
  608. Value = NULL;
  609. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  610. if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  611. Id = TokenNumericValue;
  612. if ((t = McGetToken( FALSE )) == MCTOK_COLON) {
  613. if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  614. Value = McMakeString( TokenCharValue );
  615. } else {
  616. McInputErrorA( "File name must follow =%ld:", TRUE, (PVOID)UlongToPtr(Id) );
  617. return( FALSE );
  618. }
  619. } else {
  620. if (ValueRequired) {
  621. McInputErrorA( "Colon must follow =%ld", TRUE, (PVOID)UlongToPtr(Id) );
  622. return( FALSE );
  623. }
  624. McUnGetToken();
  625. }
  626. } else {
  627. McInputErrorW( L"Number must follow %s=", TRUE, Name );
  628. return( FALSE );
  629. }
  630. } else {
  631. McInputErrorW( L"Equal sign name must follow %s", TRUE, Name );
  632. return( FALSE );
  633. }
  634. if (Id > MaximumValue) {
  635. McInputErrorA( "Value is too large (> %lx)", TRUE, (PVOID)UlongToPtr(MaximumValue) );
  636. return( FALSE );
  637. }
  638. p = McAddName( NameListHead, Name, Id, Value );
  639. free( Name );
  640. }
  641. else if (t == MCTOK_COLON && p) {
  642. if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  643. p->CodePage = (USHORT)TokenNumericValue;
  644. if (!IsValidCodePage(TokenNumericValue)) {
  645. McInputErrorW( L"CodePage %d is invalid", TRUE, (PVOID)UlongToPtr(TokenNumericValue) );
  646. return( FALSE );
  647. }
  648. if (VerboseOutput) {
  649. fprintf( stderr, "Using CodePage %d for Language %04x\n", TokenNumericValue, Id);
  650. }
  651. } else {
  652. McInputErrorW( L"CodePage must follow %s=:", TRUE, Name );
  653. return( FALSE );
  654. }
  655. }
  656. }
  657. return( FALSE );
  658. }
  659. BOOL
  660. McParseName(
  661. PNAME_INFO NameListHead,
  662. PNAME_INFO *Result
  663. )
  664. {
  665. unsigned int t;
  666. PNAME_INFO p;
  667. if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  668. p = McFindName( NameListHead, TokenCharValue );
  669. if (p != NULL) {
  670. *Result = p;
  671. return( TRUE );
  672. } else {
  673. McInputErrorW( L"Invalid name - %s", TRUE, TokenCharValue );
  674. }
  675. } else {
  676. McInputErrorW( L"Missing name after %s=", TRUE, TokenKeyword->Name );
  677. }
  678. return( FALSE );
  679. }