Leaked source code of windows server 2003
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.

784 lines
30 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. free(MessageInfo);
  285. return( FALSE );
  286. }
  287. MessageIdSeen = TRUE;
  288. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  289. if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  290. MessageInfo->Id = TokenNumericValue;
  291. MessageInfo->Method = MSG_ABSOLUTE;
  292. } else
  293. if (t == MCTOK_PLUS) {
  294. if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  295. MessageInfo->Id = TokenNumericValue;
  296. MessageInfo->Method = MSG_PLUS_VALUE;
  297. } else {
  298. McInputErrorW( L"Number must follow %s=+", TRUE, TokenKeyword->Name );
  299. free(MessageInfo);
  300. return( FALSE );
  301. }
  302. } else {
  303. McUnGetToken();
  304. }
  305. } else {
  306. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  307. free(MessageInfo);
  308. return( FALSE );
  309. }
  310. break;
  311. case MCTOK_SEVERITY_KEYWORD:
  312. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  313. if (!McParseName( SeverityNames, &CurrentSeverityName )) {
  314. free(MessageInfo);
  315. return( FALSE );
  316. }
  317. } else {
  318. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  319. free(MessageInfo);
  320. return( FALSE );
  321. }
  322. break;
  323. case MCTOK_FACILITY_KEYWORD:
  324. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  325. if (!McParseName( FacilityNames, &CurrentFacilityName )) {
  326. free(MessageInfo);
  327. return( FALSE );
  328. }
  329. } else {
  330. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  331. free(MessageInfo);
  332. return( FALSE );
  333. }
  334. break;
  335. case MCTOK_SYMBOLNAME_KEYWORD:
  336. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  337. if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  338. MessageInfo->SymbolicName = McMakeString( TokenCharValue );
  339. } else {
  340. McInputErrorW( L"Symbol name must follow %s=+", TRUE, TokenKeyword->Name );
  341. free(MessageInfo);
  342. return( FALSE );
  343. }
  344. } else {
  345. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  346. free(MessageInfo);
  347. return( FALSE );
  348. }
  349. break;
  350. case MCTOK_END_OF_LINE_COMMENT:
  351. MessageInfo->EndOfLineComment = McMakeString( TokenCharValue );
  352. break;
  353. case MCTOK_LANGUAGE_KEYWORD:
  354. McUnGetToken();
  355. if (MessageInfo->Method == MSG_PLUS_ONE) {
  356. MessageInfo->Id = CurrentFacilityName->LastId + 1;
  357. } else
  358. if (MessageInfo->Method == MSG_PLUS_VALUE) {
  359. MessageInfo->Id = CurrentFacilityName->LastId + MessageInfo->Id;
  360. }
  361. if (MessageInfo->Id > 0xFFFFL) {
  362. McInputErrorA( "Message Id value (%lx) too large", TRUE, (PVOID)UlongToPtr(MessageInfo->Id) );
  363. free(MessageInfo);
  364. return( FALSE );
  365. }
  366. MessageInfo->Id |= (CurrentSeverityName->Id << 30) |
  367. CustomerMsgIdBit |
  368. (CurrentFacilityName->Id << 16);
  369. fprintf( HeaderFile, "//\r\n" );
  370. if (MessageInfo->SymbolicName) {
  371. fprintf( HeaderFile, "// MessageId: %ws\r\n",
  372. MessageInfo->SymbolicName
  373. );
  374. } else {
  375. fprintf( HeaderFile, "// MessageId: 0x%08lXL (No symbolic name defined)\r\n",
  376. MessageInfo->Id
  377. );
  378. }
  379. fprintf( HeaderFile, "//\r\n" );
  380. fprintf( HeaderFile, "// MessageText:\r\n" );
  381. fprintf( HeaderFile, "//\r\n" );
  382. if (McParseMessageText( MessageInfo )) {
  383. fprintf( HeaderFile, "//\r\n" );
  384. if (MessageInfo->SymbolicName) {
  385. if (GenerateDebugFile) {
  386. fprintf( DebugFile, " (%ws) %ws, \"%ws\",\n",
  387. wszMessageType,
  388. MessageInfo->SymbolicName,
  389. MessageInfo->SymbolicName
  390. );
  391. }
  392. if (MessageIdTypeMacro != NULL) {
  393. fprintf( HeaderFile, GenerateDecimalMessageValues ?
  394. "#define %-32ws %ws(%ldL)" :
  395. "#define %-32ws %ws(0x%08lXL)",
  396. MessageInfo->SymbolicName,
  397. MessageIdTypeMacro,
  398. MessageInfo->Id
  399. );
  400. } else {
  401. if (MessageIdTypeName != NULL) {
  402. fprintf( HeaderFile, GenerateDecimalMessageValues ?
  403. "#define %-32ws ((%ws)%ldL)" :
  404. "#define %-32ws ((%ws)0x%08lXL)",
  405. MessageInfo->SymbolicName,
  406. wszMessageType,
  407. MessageInfo->Id
  408. );
  409. } else {
  410. fprintf( HeaderFile, GenerateDecimalMessageValues ?
  411. "#define %-32ws %ldL" :
  412. "#define %-32ws 0x%08lXL",
  413. MessageInfo->SymbolicName,
  414. MessageInfo->Id
  415. );
  416. }
  417. }
  418. }
  419. if (MessageInfo->EndOfLineComment) {
  420. fprintf( HeaderFile, " %ws", MessageInfo->EndOfLineComment );
  421. } else {
  422. fprintf( HeaderFile, "\r\n" );
  423. }
  424. fprintf( HeaderFile, "\r\n" );
  425. //
  426. // Scan the existing messages to see if this message
  427. // exists in the message file.
  428. //
  429. // If it does, generate and error for the user. Otherwise
  430. // insert new message in list in ascending Id order.
  431. //
  432. pp = &Messages;
  433. while (MessageInfoTemp = *pp) {
  434. if (MessageInfoTemp->Id == MessageInfo->Id) {
  435. if (MessageInfo->SymbolicName && MessageInfoTemp->SymbolicName) {
  436. fprintf( stderr,
  437. "%s(%d) : error : Duplicate message ID - 0x%x (%ws and %ws)\n",
  438. MessageFileName,
  439. MessageFileLineNumber,
  440. MessageInfo->Id,
  441. MessageInfoTemp->SymbolicName,
  442. MessageInfo->SymbolicName
  443. );
  444. } else {
  445. McInputErrorA( "Duplicate message ID - 0x%lx", TRUE, (PVOID)UlongToPtr(MessageInfo->Id) );
  446. }
  447. } else {
  448. if (MessageInfoTemp->Id > MessageInfo->Id) {
  449. break;
  450. }
  451. }
  452. pp = &MessageInfoTemp->Next;
  453. }
  454. MessageInfo->Next = *pp;
  455. *pp = MessageInfo;
  456. CurrentMessage = MessageInfo;
  457. CurrentFacilityName->LastId = MessageInfo->Id & 0xFFFF;
  458. return( TRUE );
  459. } else {
  460. free(MessageInfo);
  461. return( FALSE );
  462. }
  463. default:
  464. McInputErrorW( L"Invalid message definition token - '%s'", TRUE, TokenCharValue );
  465. free(MessageInfo);
  466. return( FALSE );
  467. }
  468. }
  469. free(MessageInfo);
  470. return( FALSE );
  471. }
  472. WCHAR MessageTextBuffer[ 32767 ];
  473. BOOL
  474. McParseMessageText(
  475. PMESSAGE_INFO MessageInfo
  476. )
  477. {
  478. PLANGUAGE_INFO MessageText, *pp;
  479. WCHAR *src, *dst;
  480. unsigned int t, n;
  481. BOOL FirstLanguageProcessed;
  482. pp = &MessageInfo->MessageText;
  483. FirstLanguageProcessed = FALSE;
  484. while ((t = McGetToken( TRUE )) != MCTOK_END_OF_FILE) {
  485. if (t == MCTOK_LANGUAGE_KEYWORD) {
  486. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  487. if (!McParseName( LanguageNames, &CurrentLanguageName )) {
  488. return( FALSE );
  489. }
  490. GetCPInfo(CurrentLanguageName->CodePage, &CPInfo);
  491. } else {
  492. McInputErrorW( L"Equal sign must follow %s", TRUE, TokenKeyword->Name );
  493. return( FALSE );
  494. }
  495. } else {
  496. McUnGetToken();
  497. break;
  498. }
  499. MessageText = malloc( sizeof( *MessageText ) );
  500. MessageText->Next = NULL;
  501. MessageText->Id = CurrentLanguageName->Id;
  502. MessageText->Length = 0;
  503. MessageText->Text = NULL;
  504. dst = MessageTextBuffer;
  505. *MessageTextBuffer = L'\0';
  506. while (src = McGetLine()) {
  507. n = wcslen( MessageTextBuffer );
  508. // If the message buffer is complete, see if this is a '.' record.
  509. if (((n == 0) || *(MessageTextBuffer+n-1) == L'\n') &&
  510. !wcscmp( src, L".\r\n" )) {
  511. if (MessageText->Length == 0) {
  512. if (MessageInfo->SymbolicName) {
  513. wcscpy( dst, MessageInfo->SymbolicName );
  514. } else {
  515. swprintf( dst, L"No symbolic name defined for0x%08lXL", MessageInfo->Id );
  516. }
  517. wcscat( dst, L"\r\n" );
  518. if (!FirstLanguageProcessed) {
  519. fprintf( HeaderFile, "// %ws", dst );
  520. }
  521. n = wcslen( dst );
  522. dst += n;
  523. MessageText->Length += n;
  524. }
  525. McSkipLine();
  526. break;
  527. }
  528. else if (!_wcsnicmp( src, L"LanguageId=", 11 ) ||
  529. !_wcsnicmp( src, L"MessageId=", 10 )) {
  530. McInputErrorA( "Unterminated message definition", TRUE, NULL );
  531. return( FALSE );
  532. }
  533. if (!FirstLanguageProcessed) {
  534. // To write DBCS comments to the header file.
  535. //
  536. // fprintf() does not work correctly with Unicode
  537. // to write DBCS characters. Convert Unicode to
  538. // MultiByte and use the Ansi string instead...
  539. char * pch;
  540. int len = WideCharToMultiByte(CurrentLanguageName->CodePage,
  541. 0, // No flags
  542. src, // The buffer to convert
  543. -1, // It's zero terminated
  544. NULL,
  545. 0, // Tell us how much to allocate
  546. NULL, // No default char
  547. NULL); // No used default char
  548. pch = malloc(len + 1);
  549. WideCharToMultiByte(CurrentLanguageName->CodePage,
  550. 0,
  551. src,
  552. -1,
  553. pch, // The buffer to fill in
  554. len, // How big it is
  555. NULL,
  556. NULL);
  557. fprintf( HeaderFile, "// %s", pch );
  558. free(pch);
  559. }
  560. n = wcslen( src );
  561. if (MessageText->Length + n > sizeof( MessageTextBuffer )) {
  562. McInputErrorA( "Message text too long (> %ld)", TRUE,
  563. (PVOID)UlongToPtr((ULONG)sizeof( MessageTextBuffer ))
  564. );
  565. return( FALSE );
  566. }
  567. wcscpy( dst, src );
  568. dst += n;
  569. MessageText->Length += n;
  570. if (MaxMessageLength != 0 && (MessageText->Length > (ULONG)MaxMessageLength)) {
  571. McInputErrorA( "Message text larger than size specified by -m %d",
  572. TRUE,
  573. (PVOID)IntToPtr(MaxMessageLength)
  574. );
  575. }
  576. }
  577. *dst = L'\0';
  578. // Add NULL terminator if requested
  579. if (NULLTerminate)
  580. {
  581. MessageText->Length -= 2;
  582. MessageTextBuffer[MessageText->Length] = L'\0';
  583. }
  584. n = (((USHORT)MessageText->Length) + 1) * sizeof( WCHAR );
  585. MessageText->Text = malloc( n );
  586. memcpy( MessageText->Text, MessageTextBuffer, n );
  587. if (UnicodeOutput)
  588. MessageText->Length = n - sizeof( WCHAR );
  589. else
  590. MessageText->Length = WideCharToMultiByte(
  591. CurrentLanguageName->CodePage,
  592. 0, MessageTextBuffer, MessageText->Length,
  593. NULL, 0, NULL, NULL );
  594. *pp = MessageText;
  595. pp = &MessageText->Next;
  596. FirstLanguageProcessed = TRUE;
  597. }
  598. return( TRUE );
  599. }
  600. BOOL
  601. McParseNameList(
  602. PNAME_INFO *NameListHead,
  603. BOOL ValueRequired,
  604. ULONG MaximumValue
  605. )
  606. {
  607. unsigned int t;
  608. PNAME_INFO p = NULL;
  609. WCHAR *Name;
  610. ULONG Id;
  611. PVOID Value;
  612. Name = NULL;
  613. Id = 0;
  614. while ((t = McGetToken( FALSE )) != MCTOK_END_OF_FILE) {
  615. if (t == MCTOK_RIGHT_PAREN) {
  616. return( TRUE );
  617. }
  618. if (t == MCTOK_NAME) {
  619. Name = McMakeString( TokenCharValue );
  620. Id = 0;
  621. Value = NULL;
  622. if ((t = McGetToken( FALSE )) == MCTOK_EQUAL) {
  623. if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  624. Id = TokenNumericValue;
  625. if ((t = McGetToken( FALSE )) == MCTOK_COLON) {
  626. if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  627. Value = McMakeString( TokenCharValue );
  628. } else {
  629. McInputErrorA( "File name must follow =%ld:", TRUE, (PVOID)UlongToPtr(Id) );
  630. return( FALSE );
  631. }
  632. } else {
  633. if (ValueRequired) {
  634. McInputErrorA( "Colon must follow =%ld", TRUE, (PVOID)UlongToPtr(Id) );
  635. return( FALSE );
  636. }
  637. McUnGetToken();
  638. }
  639. } else {
  640. McInputErrorW( L"Number must follow %s=", TRUE, Name );
  641. return( FALSE );
  642. }
  643. } else {
  644. McInputErrorW( L"Equal sign name must follow %s", TRUE, Name );
  645. return( FALSE );
  646. }
  647. if (Id > MaximumValue) {
  648. McInputErrorA( "Value is too large (> %lx)", TRUE, (PVOID)UlongToPtr(MaximumValue) );
  649. return( FALSE );
  650. }
  651. p = McAddName( NameListHead, Name, Id, Value );
  652. free( Name );
  653. }
  654. else if (t == MCTOK_COLON && p) {
  655. if ((t = McGetToken( FALSE )) == MCTOK_NUMBER) {
  656. p->CodePage = (USHORT)TokenNumericValue;
  657. if (!IsValidCodePage(TokenNumericValue)) {
  658. McInputErrorW( L"CodePage %d is invalid", TRUE, (PVOID)UlongToPtr(TokenNumericValue) );
  659. return( FALSE );
  660. }
  661. if (VerboseOutput) {
  662. fprintf( stderr, "Using CodePage %d for Language %04x\n", TokenNumericValue, Id);
  663. }
  664. } else {
  665. McInputErrorW( L"CodePage must follow %s=:", TRUE, Name );
  666. return( FALSE );
  667. }
  668. }
  669. }
  670. return( FALSE );
  671. }
  672. BOOL
  673. McParseName(
  674. PNAME_INFO NameListHead,
  675. PNAME_INFO *Result
  676. )
  677. {
  678. unsigned int t;
  679. PNAME_INFO p;
  680. if ((t = McGetToken( FALSE )) == MCTOK_NAME) {
  681. p = McFindName( NameListHead, TokenCharValue );
  682. if (p != NULL) {
  683. *Result = p;
  684. return( TRUE );
  685. } else {
  686. McInputErrorW( L"Invalid name - %s", TRUE, TokenCharValue );
  687. }
  688. } else {
  689. McInputErrorW( L"Missing name after %s=", TRUE, TokenKeyword->Name );
  690. }
  691. return( FALSE );
  692. }