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.

1075 lines
36 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* RCP.C - */
  4. /* */
  5. /* Resource Compiler 3.00 - Top Level Parsing routines */
  6. /* */
  7. /****************************************************************************/
  8. #include "rc.h"
  9. static BOOL fFontDirRead = FALSE;
  10. BOOL bExternParse = FALSE;
  11. WORD language = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
  12. LONG version = 0;
  13. LONG characteristics = 0;
  14. static int rowError = 0;
  15. static int colError = 0;
  16. static int idError = 0;
  17. /*--------------------------------------------------------------------------*/
  18. /* */
  19. /* ParseError3() - */
  20. /* */
  21. /*--------------------------------------------------------------------------*/
  22. void
  23. ParseError3(
  24. int id
  25. )
  26. {
  27. // Don't get caught giving the same error over and over and over...
  28. if ((Nerrors > 0) && (idError == id) && (rowError == token.row) && (colError == token.col))
  29. quit("\n");
  30. SendError("\n");
  31. SendError(Msg_Text);
  32. if (++Nerrors > 25)
  33. quit("\n");
  34. rowError = token.row;
  35. colError = token.col;
  36. idError = id;
  37. }
  38. /*--------------------------------------------------------------------------*/
  39. /* */
  40. /* ParseError2() - */
  41. /* */
  42. /*--------------------------------------------------------------------------*/
  43. void
  44. ParseError2(
  45. int id,
  46. PWCHAR arg
  47. )
  48. {
  49. // Don't get caught giving the same error over and over and over...
  50. if ((Nerrors > 0) && (idError == id) && (rowError == token.row) && (colError == token.col))
  51. quit("\n");
  52. SendError("\n");
  53. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(id), curFile, token.row, arg);
  54. SendError(Msg_Text);
  55. if (++Nerrors > 25)
  56. quit("\n");
  57. rowError = token.row;
  58. colError = token.col;
  59. idError = id;
  60. }
  61. /*--------------------------------------------------------------------------*/
  62. /* */
  63. /* ParseError1() - */
  64. /* */
  65. /*--------------------------------------------------------------------------*/
  66. void
  67. ParseError1(
  68. int id
  69. )
  70. {
  71. // Don't get caught giving the same error over and over and over...
  72. if ((Nerrors > 0) && (idError == id) && (rowError == token.row) && (colError == token.col))
  73. quit("\n");
  74. SendError("\n");
  75. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(id), curFile, token.row);
  76. SendError(Msg_Text);
  77. if (++Nerrors > 25)
  78. quit("\n");
  79. rowError = token.row;
  80. colError = token.col;
  81. idError = id;
  82. }
  83. /*--------------------------------------------------------------------------*/
  84. /* */
  85. /* GetFileName() - */
  86. /* */
  87. /*--------------------------------------------------------------------------*/
  88. /* Read in a filename from the RC file. */
  89. LONG
  90. GetFileName(
  91. VOID
  92. )
  93. {
  94. PFILE fh;
  95. LONG size;
  96. CHAR szFilename[_MAX_PATH];
  97. CHAR buf[_MAX_PATH];
  98. // Note: Always use the Ansi codepage here. uiCodePage may have been
  99. // modified by a codepage pragma in the source file.
  100. WideCharToMultiByte(GetACP(), 0, tokenbuf, -1, buf, _MAX_PATH, NULL, NULL);
  101. searchenv(buf, "INCLUDE", szFilename);
  102. if ( szFilename[0] && ((fh = fopen(szFilename, "rb")) != NULL)) {
  103. size = MySeek(fh, 0L, SEEK_END); /* find size of file */
  104. MySeek(fh, 0L, SEEK_SET); /* return to start of file */
  105. CtlFile(fh);
  106. return(size);
  107. } else {
  108. ParseError2(2135, (PWCHAR)buf);
  109. return 0;
  110. }
  111. }
  112. /*--------------------------------------------------------------------------*/
  113. /* */
  114. /* AddStringToBin() - */
  115. /* */
  116. /*--------------------------------------------------------------------------*/
  117. /* adds ordinal if non-zero, otherwise adds string. In either case, puts */
  118. /* it in a field of NCHARS [16] */
  119. VOID
  120. AddStringToBin(
  121. USHORT ord,
  122. WCHAR *sz
  123. )
  124. {
  125. USHORT n1 = 0xFFFF;
  126. /* Is this an ordinal type? */
  127. if (ord) {
  128. MyWrite(fhBin, (PCHAR)&n1, sizeof(USHORT)); /* 0xFFFF */
  129. MyWrite(fhBin, (PCHAR)&ord, sizeof(USHORT));
  130. } else {
  131. MyWrite(fhBin, (PVOID)sz, (wcslen(sz)+1) * sizeof(WCHAR));
  132. }
  133. }
  134. PWCHAR pTypeName[] =
  135. {
  136. NULL, // 0
  137. L"CURSOR", // 1 RT_CURSOR
  138. L"BITMAP", // 2 RT_BITMAP
  139. L"ICON", // 3 RT_ICON
  140. L"MENU", // 4 RT_MENU
  141. L"DIALOG", // 5 RT_DIALOG
  142. L"STRING", // 6 RT_STRING
  143. L"FONTDIR", // 7 RT_FONTDIR
  144. L"FONT", // 8 RT_FONT
  145. L"ACCELERATOR", // 9 RT_ACCELERATOR
  146. L"RCDATA", // 10 RT_RCDATA
  147. L"MESSAGETABLE", // 11 RT_MESSAGETABLE
  148. L"GROUP_CURSOR", // 12 RT_GROUP_CURSOR
  149. NULL, // 13 RT_NEWBITMAP -- according to NT
  150. L"GROUP_ICON", // 14 RT_GROUP_ICON
  151. NULL, // 15 RT_NAMETABLE
  152. L"VERSION", // 16 RT_VERSION
  153. L"DIALOGEX", // 17 RT_DIALOGEX ;internal
  154. L"DLGINCLUDE", // 18 RT_DLGINCLUDE
  155. L"PLUGPLAY", // 19 RT_PLUGPLAY
  156. L"VXD", // 20 RT_VXD
  157. L"ANICURSOR", // 21 RT_ANICURSOR ;internal
  158. L"ANIICON", // 22 RT_ANIICON ;internal
  159. L"HTML" // 23 RT_HTML
  160. };
  161. // Note: Don't forget to update the same table in rcdump.c
  162. /*--------------------------------------------------------------------------*/
  163. /* */
  164. /* AddBinEntry() - */
  165. /* */
  166. /*--------------------------------------------------------------------------*/
  167. /* FORMAT: type, name, flags, length, bytes */
  168. VOID
  169. AddBinEntry(
  170. PTYPEINFO pType,
  171. PRESINFO pRes,
  172. PCHAR Array,
  173. int ArrayCount,
  174. LONG FileCount
  175. )
  176. {
  177. ULONG hdrSize = sizeof(RESADDITIONAL);
  178. ULONG t0 = 0;
  179. ULONG cbPad=0;
  180. if (!pRes->size)
  181. pRes->size = ResourceSize();
  182. if (pType->typeord == 0) {
  183. hdrSize += (wcslen(pType->type) + 1) * sizeof(WCHAR);
  184. cbPad += (wcslen(pType->type) + 1) * sizeof(WCHAR);
  185. } else {
  186. hdrSize += 2 * sizeof(WORD);
  187. }
  188. if (pRes->nameord == 0) {
  189. hdrSize += (wcslen(pRes->name) + 1) * sizeof(WCHAR);
  190. cbPad += (wcslen(pRes->name) + 1) * sizeof(WCHAR);
  191. } else {
  192. hdrSize += 2 * sizeof(WORD);
  193. }
  194. if (cbPad % 4)
  195. hdrSize += sizeof(WORD); // could only be off by 2
  196. if (fVerbose) {
  197. if (pType->typeord == 0) {
  198. if (pRes->nameord == 0)
  199. wsprintfA(Msg_Text, "\nWriting %ws:%ws,\tlang:0x%x,\tsize %d",
  200. pType->type, pRes->name, pRes->language, pRes->size);
  201. else
  202. wsprintfA(Msg_Text, "\nWriting %ws:%d,\tlang:0x%x,\tsize %d",
  203. pType->type, pRes->nameord, pRes->language, pRes->size);
  204. } else {
  205. if (pRes->nameord == 0) {
  206. if (pType->typeord <= (USHORT)(UINT_PTR)RT_LAST)
  207. wsprintfA(Msg_Text, "\nWriting %ws:%ws,\tlang:0x%x,\tsize %d",
  208. pTypeName[pType->typeord],
  209. pRes->name, pRes->language, pRes->size);
  210. else
  211. wsprintfA(Msg_Text, "\nWriting %d:%ws,\tlang:0x%x,\tsize %d",
  212. pType->typeord,
  213. pRes->name, pRes->language, pRes->size);
  214. } else {
  215. if (pType->typeord <= (USHORT)(UINT_PTR)RT_LAST)
  216. wsprintfA(Msg_Text, "\nWriting %ws:%d,\tlang:0x%x,\tsize %d",
  217. pTypeName[pType->typeord],
  218. pRes->nameord, pRes->language, pRes->size);
  219. else
  220. wsprintfA(Msg_Text, "\nWriting %d:%d,\tlang:0x%x,\tsize %d",
  221. pType->typeord,
  222. pRes->nameord, pRes->language, pRes->size);
  223. }
  224. }
  225. printf(Msg_Text);
  226. }
  227. if (fMacRsrcs) {
  228. /* record file location for the resource map and dump out
  229. resource's size */
  230. DWORD dwT;
  231. pRes->BinOffset = (long)MySeek(fhBin,0L,1) - MACDATAOFFSET;
  232. dwT = SwapLong(pRes->size);
  233. MyWrite(fhBin, &dwT, 4);
  234. } else {
  235. /* add type, name, flags, and resource length */
  236. MyWrite(fhBin, (PCHAR)&pRes->size, sizeof(ULONG));
  237. MyWrite(fhBin, (PCHAR)&hdrSize, sizeof(ULONG));
  238. AddStringToBin(pType->typeord, pType->type);
  239. AddStringToBin(pRes->nameord , pRes->name);
  240. MyAlign(fhBin);
  241. MyWrite(fhBin, (PCHAR)&t0, sizeof(ULONG)); /* data version */
  242. MyWrite(fhBin, (PCHAR)&pRes->flags, sizeof(WORD));
  243. MyWrite(fhBin, (PCHAR)&pRes->language, sizeof(WORD));
  244. MyWrite(fhBin, (PCHAR)&pRes->version, sizeof(ULONG));
  245. MyWrite(fhBin, (PCHAR)&pRes->characteristics, sizeof(ULONG));
  246. /* record file location for the .EXE construction */
  247. pRes->BinOffset = (LONG)MySeek(fhBin, 0L, SEEK_CUR);
  248. }
  249. /* write array plus contents of resource source file */
  250. WriteControl(fhBin, Array, ArrayCount, FileCount);
  251. }
  252. /*--------------------------------------------------------------------------*/
  253. /* */
  254. /* AddResToResFile(pType, pRes, Array, ArrayCount, FileCount) */
  255. /* */
  256. /* Parameters: */
  257. /* pType : Pointer to Res Type */
  258. /* pRes : Pointer to resource */
  259. /* Array : Pointer to array from which some data is to be copied into */
  260. /* the .RES file. */
  261. /* This is ignored if ArrayCount is zero. */
  262. /* ArrayCount : This is the number of bytes to be copied from "Array" */
  263. /* into the .RES file. This is zero if no copy is required*/
  264. /* FileCount : This specifies the number of bytes to be copied from */
  265. /* fhCode into fhOut. If this is -1, the complete input */
  266. /* file is to be copied into fhOut. */
  267. /* */
  268. /*------------------------------------------------------------------------*/
  269. VOID
  270. AddResToResFile(
  271. PTYPEINFO pType,
  272. PRESINFO pRes,
  273. PCHAR Array,
  274. int ArrayCount,
  275. LONG FileCount
  276. )
  277. {
  278. PRESINFO p;
  279. p = pType->pres;
  280. /* add resource to end of resource list for this type */
  281. if (p) {
  282. while (p->next)
  283. p = p->next;
  284. p->next = pRes;
  285. } else {
  286. pType->pres = pRes;
  287. }
  288. /* add the resource to the .RES File */
  289. AddBinEntry(pType, pRes, Array, ArrayCount, FileCount);
  290. /* keep track of number of resources and types */
  291. pType->nres++;
  292. ResCount++;
  293. WriteResInfo(pRes, pType, TRUE);
  294. }
  295. /*--------------------------------------------------------------------------*/
  296. /* */
  297. /* AddResType() - */
  298. /* */
  299. /*--------------------------------------------------------------------------*/
  300. PTYPEINFO
  301. AddResType(
  302. PWCHAR s,
  303. LPWSTR l
  304. )
  305. {
  306. PTYPEINFO pType;
  307. if ((pType = pTypInfo) != 0) {
  308. for (; ; ) {
  309. /* search for resource type, return if already exists */
  310. if ((s && pType->type && !wcscmp(s, pType->type)) ||
  311. (!s && l && pType->typeord == (USHORT)l))
  312. return(pType);
  313. else if (!pType->next)
  314. break;
  315. else
  316. pType = pType->next;
  317. }
  318. /* if not in list, add space for it */
  319. pType->next = (PTYPEINFO)MyAlloc(sizeof(TYPEINFO));
  320. pType = pType->next;
  321. } else {
  322. /* allocate space for resource list */
  323. pTypInfo = (PTYPEINFO)MyAlloc(sizeof(TYPEINFO));
  324. pType = pTypInfo;
  325. }
  326. /* fill allocated space with name and ordinal, and clear the resources
  327. of this type */
  328. pType->type = MyMakeStr(s);
  329. pType->typeord = (USHORT)l;
  330. pType->nres = 0;
  331. pType->pres = NULL;
  332. return(pType);
  333. }
  334. /*--------------------------------------------------------------------------*/
  335. /* */
  336. /* DGetMemFlags() - */
  337. /* */
  338. /*--------------------------------------------------------------------------*/
  339. int
  340. DGetMemFlags (
  341. PRESINFO pRes
  342. )
  343. {
  344. if (token.type == NUMLIT)
  345. // this is a numeric value, not a mem flag -- this means we're done
  346. // processing memory flags
  347. return(FALSE);
  348. /* adjust memory flags of resource */
  349. switch (token.val) {
  350. case TKMOVEABLE:
  351. pRes->flags |= NSMOVE;
  352. break;
  353. case TKFIXED:
  354. pRes->flags &= ~(NSMOVE | NSDISCARD);
  355. break;
  356. case TKPURE :
  357. pRes->flags |= NSPURE;
  358. break;
  359. case TKIMPURE :
  360. pRes->flags &= ~(NSPURE | NSDISCARD);
  361. break;
  362. case TKPRELOAD:
  363. pRes->flags |= NSPRELOAD;
  364. break;
  365. case TKLOADONCALL:
  366. pRes->flags &= ~NSPRELOAD;
  367. break;
  368. case TKDISCARD:
  369. pRes->flags |= NSMOVE | NSPURE | NSDISCARD;
  370. break;
  371. case TKEXSTYLE:
  372. GetToken(FALSE); /* ignore '=' */
  373. if (token.type != EQUAL)
  374. ParseError1(2136);
  375. GetTokenNoComma(TOKEN_NOEXPRESSION);
  376. GetFullExpression(&pRes->exstyleT, GFE_ZEROINIT);
  377. break;
  378. /* if current token not memory flag, return FALSE to indicate not
  379. to continue parsing flags */
  380. default:
  381. return(FALSE);
  382. }
  383. GetToken(FALSE);
  384. /* TRUE ==> found memory flag */
  385. return(TRUE);
  386. }
  387. /*--------------------------------------------------------------------------*/
  388. /* */
  389. /* AddDefaultTypes() - */
  390. /* */
  391. /*--------------------------------------------------------------------------*/
  392. VOID
  393. AddDefaultTypes(
  394. VOID
  395. )
  396. {
  397. AddResType(L"CURSOR", RT_GROUP_CURSOR);
  398. AddResType(L"ICON", RT_GROUP_ICON);
  399. AddResType(L"BITMAP", RT_BITMAP);
  400. AddResType(L"MENU", RT_MENU);
  401. AddResType(L"DIALOG", RT_DIALOG);
  402. AddResType(L"STRINGTABLE", RT_STRING);
  403. AddResType(L"FONTDIR", RT_FONTDIR);
  404. AddResType(L"FONT", RT_FONT);
  405. AddResType(L"ACCELERATORS", RT_ACCELERATOR);
  406. AddResType(L"RCDATA", RT_RCDATA);
  407. AddResType(L"MESSAGETABLE", RT_MESSAGETABLE);
  408. AddResType(L"VERSIONINFO", RT_VERSION);
  409. AddResType(L"DLGINCLUDE", RT_DLGINCLUDE);
  410. AddResType(L"MENUEX", RT_MENUEX);
  411. AddResType(L"DIALOGEX", RT_DIALOGEX);
  412. AddResType(L"PLUGPLAY", RT_PLUGPLAY);
  413. AddResType(L"VXD", RT_VXD);
  414. // AFX resource types.
  415. AddResType(L"DLGINIT", RT_DLGINIT);
  416. AddResType(L"TOOLBAR", RT_TOOLBAR);
  417. AddResType(L"ANIICON", RT_ANIICON);
  418. AddResType(L"ANICURSOR", RT_ANICURSOR);
  419. AddResType(L"HTML", RT_HTML);
  420. }
  421. /*--------------------------------------------------------------------------*/
  422. /* */
  423. /* AddFontDir() - */
  424. /* */
  425. /*--------------------------------------------------------------------------*/
  426. VOID
  427. AddFontDir(
  428. VOID
  429. )
  430. {
  431. PRESINFO pRes;
  432. PTYPEINFO pType;
  433. PFONTDIR pFont;
  434. /* make new resource */
  435. pRes = (PRESINFO)MyAlloc(sizeof(RESINFO));
  436. pRes->language = language;
  437. pRes->version = version;
  438. pRes->characteristics = characteristics;
  439. pRes->name = MyMakeStr(L"FONTDIR");
  440. /* find or create the type list */
  441. pType = AddResType(NULL, RT_FONTDIR);
  442. CtlInit();
  443. WriteWord(nFontsRead);
  444. pFont = pFontList;
  445. while (pFont) {
  446. WriteWord(pFont->ordinal);
  447. WriteBuffer((PCHAR)(pFont + 1), pFont->nbyFont);
  448. pFont = pFont->next;
  449. }
  450. pRes->flags = NSMOVE | NSPRELOAD;
  451. /* write to the .RES file */
  452. SaveResFile(pType, pRes);
  453. }
  454. /*--------------------------------------------------------------------------*/
  455. /* */
  456. /* ReadRF() - */
  457. /* */
  458. /*--------------------------------------------------------------------------*/
  459. /* top level parsing function: recognizes an RC script */
  460. int
  461. ReadRF(
  462. VOID
  463. )
  464. {
  465. PRESINFO pRes;
  466. PTYPEINFO pType;
  467. ULONG zero=0;
  468. WORD ffff=0xffff;
  469. ULONG hdrSize = sizeof(RESADDITIONAL) + 2 * (sizeof(WORD) * 2);
  470. ResCount = 0;
  471. nFontsRead = 0;
  472. /* Initialize data structures. */
  473. AddDefaultTypes();
  474. if (!fMacRsrcs) {
  475. /* write 32-bit header for empty resource/signature */
  476. MyWrite(fhBin, (PCHAR)&zero, sizeof(ULONG));
  477. MyWrite(fhBin, (PCHAR)&hdrSize, sizeof(ULONG));
  478. MyWrite(fhBin, (PCHAR)&ffff, sizeof(WORD));
  479. MyWrite(fhBin, (PCHAR)&zero, sizeof(WORD));
  480. MyWrite(fhBin, (PCHAR)&ffff, sizeof(WORD));
  481. MyWrite(fhBin, (PCHAR)&zero, sizeof(WORD));
  482. MyWrite(fhBin, (PCHAR)&zero, sizeof(ULONG));
  483. MyWrite(fhBin, (PCHAR)&zero, sizeof(WORD));
  484. MyWrite(fhBin, (PCHAR)&zero, sizeof(WORD));
  485. MyWrite(fhBin, (PCHAR)&zero, sizeof(ULONG));
  486. MyWrite(fhBin, (PCHAR)&zero, sizeof(ULONG));
  487. }
  488. CtlAlloc();
  489. if (fAFXSymbols) {
  490. char* pch = inname;
  491. // write out first HWB resource
  492. CtlInit();
  493. pRes = (PRESINFO)MyAlloc(sizeof(RESINFO));
  494. pRes->language = language;
  495. pRes->version = version;
  496. pRes->characteristics = characteristics;
  497. pRes->size = sizeof(DWORD);
  498. pRes->flags = 0;
  499. pRes->name = 0;
  500. pRes->nameord = 1;
  501. WriteLong(0); /* space for file pointer */
  502. while (*pch) {
  503. WriteByte(*pch++);
  504. pRes->size++;
  505. }
  506. WriteByte(0);
  507. pRes->size++;
  508. pType = AddResType(L"HWB", 0);
  509. SaveResFile(pType, pRes);
  510. lOffIndex = pRes->BinOffset;
  511. }
  512. /* Process the RC file. */
  513. do {
  514. token.sym.name[0] = L'\0';
  515. token.sym.nID = 0;
  516. /* Find the beginning of the next resource. */
  517. if (!GetNameOrd())
  518. break;
  519. if (!wcscmp(tokenbuf, L"LANGUAGE")) {
  520. language = GetLanguage();
  521. continue;
  522. } else if (!wcscmp(tokenbuf, L"VERSION")) {
  523. GetToken(FALSE);
  524. if (token.type != NUMLIT)
  525. ParseError1(2139);
  526. version = token.longval;
  527. continue;
  528. } else if (!wcscmp(tokenbuf, L"CHARACTERISTICS")) {
  529. GetToken(FALSE);
  530. if (token.type != NUMLIT)
  531. ParseError1(2140);
  532. characteristics = token.longval;
  533. continue;
  534. }
  535. /* Print a dot for each resource processed. */
  536. if (fVerbose) {
  537. printf(".");
  538. }
  539. /* Allocate space for the new resources Info structure. */
  540. pRes = (PRESINFO)MyAlloc(sizeof(RESINFO));
  541. pRes->language = language;
  542. pRes->version = version;
  543. pRes->characteristics = characteristics;
  544. if (token.sym.name[0]) {
  545. /* token has a real symbol associated with it */
  546. memcpy(&pRes->sym, &token.sym, sizeof(SYMINFO));
  547. } else {
  548. pRes->sym.name[0] = L'\0';
  549. }
  550. if (!token.val) {
  551. if (wcslen(tokenbuf) > MAXTOKSTR-1) {
  552. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(4206), curFile, token.row);
  553. SendError(Msg_Text);
  554. tokenbuf[MAXTOKSTR-1] = L'\0';
  555. token.val = MAXTOKSTR-2;
  556. }
  557. pRes->name = MyMakeStr(tokenbuf);
  558. } else {
  559. pRes->nameord = token.val;
  560. }
  561. /* If not a string table, find out what kind of resource follows.
  562. * The StringTable is a special case since the Name field is the
  563. * string's ID number mod 16.
  564. */
  565. if ((pRes->name == NULL) || wcscmp(pRes->name, L"STRINGTABLE")) {
  566. if (!GetNameOrd())
  567. break;
  568. if (!token.val) {
  569. if (wcslen(tokenbuf) > MAXTOKSTR-1) {
  570. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(4207), curFile, token.row);
  571. SendError(Msg_Text);
  572. tokenbuf[MAXTOKSTR-1] = L'\0';
  573. token.val = MAXTOKSTR-2;
  574. }
  575. if (!wcscmp(tokenbuf, L"STRINGTABLE")) {
  576. // User attempted to create a named string table... Bail
  577. ParseError1(2255);
  578. pRes->name = MyMakeStr(tokenbuf);
  579. goto ItsAStringTable;
  580. }
  581. pType = AddResType(tokenbuf, MAKEINTRESOURCE(0));
  582. }
  583. else
  584. pType = AddResType(NULL, MAKEINTRESOURCE(token.val));
  585. if (!pType)
  586. return(errorCount == 0);
  587. /* Parse any user specified memory flags. */
  588. GetToken(FALSE);
  589. switch ((INT_PTR)pType->typeord) {
  590. /* Calculated resources default to discardable. */
  591. case (INT_PTR)RT_ICON:
  592. case (INT_PTR)RT_CURSOR:
  593. case (INT_PTR)RT_FONT:
  594. case (INT_PTR)RT_DIALOG:
  595. case (INT_PTR)RT_MENU:
  596. case (INT_PTR)RT_DLGINCLUDE:
  597. case (INT_PTR)RT_DIALOGEX:
  598. case (INT_PTR)RT_MENUEX:
  599. pRes->flags = NSMOVE | NSPURE | NSDISCARD;
  600. break;
  601. case (INT_PTR)RT_GROUP_ICON:
  602. case (INT_PTR)RT_GROUP_CURSOR:
  603. pRes->flags = NSMOVE | NSDISCARD;
  604. break;
  605. /* All other resources default to moveable. */
  606. default:
  607. pRes->flags = NSMOVE | NSPURE;
  608. break;
  609. }
  610. /* adjust according to the user's specifications
  611. */
  612. while (DGetMemFlags(pRes))
  613. ;
  614. // write out start of new resource
  615. WriteResInfo(pRes, pType, FALSE);
  616. } else {
  617. ItsAStringTable:
  618. /* Parse any user specified memory flags. */
  619. GetToken(FALSE);
  620. /* String and Error resources default to discardable. */
  621. pRes->flags = NSMOVE | NSPURE | NSDISCARD;
  622. while (DGetMemFlags(pRes))
  623. ;
  624. pType = NULL;
  625. }
  626. if (!pType) {
  627. /* parse the string table, if that's what it is */
  628. if ((pRes->name != NULL) && (!wcscmp(pRes->name, L"STRINGTABLE"))) {
  629. if (GetTable(pRes) == NULL)
  630. break;
  631. } else {
  632. ParseError1(2141);
  633. }
  634. } else {
  635. CtlInit();
  636. pRes->size = 0L;
  637. /* call parsing and generating functions specific to the various
  638. resource types */
  639. switch ((INT_PTR)pType->typeord) {
  640. case (INT_PTR)RT_DIALOGEX:
  641. /* allocate dialog memory */
  642. pLocDlg = (PDLGHDR) MyAlloc(sizeof(DLGHDR));
  643. /* parse dialog box */
  644. GetDlg(pRes, pLocDlg, TRUE);
  645. /* write dialog box */
  646. SaveResFile(AddResType(L"DIALOG", 0), pRes);
  647. /* free dialog memory */
  648. MyFree(pLocDlg);
  649. break;
  650. case (INT_PTR)RT_DIALOG:
  651. /* allocate dialog memory */
  652. pLocDlg = (PDLGHDR) MyAlloc(sizeof(DLGHDR));
  653. /* parse dialog box */
  654. GetDlg(pRes, pLocDlg, FALSE);
  655. /* write dialog box */
  656. SaveResFile(pType, pRes);
  657. /* free dialog memory */
  658. MyFree(pLocDlg);
  659. break;
  660. case (INT_PTR)RT_ACCELERATOR:
  661. GetAccelerators(pRes);
  662. SaveResFile(pType, pRes);
  663. break;
  664. case (INT_PTR)RT_MENUEX:
  665. WriteWord(MENUITEMTEMPLATEVERSIONNUMBER);
  666. WriteWord(MENUITEMTEMPLATEBYTESINHEADER);
  667. ParseMenu(FALSE, pRes);
  668. SaveResFile(AddResType(L"MENU", 0), pRes);
  669. break;
  670. case (INT_PTR)RT_MENU:
  671. WriteWord(OLDMENUITEMTEMPLATEVERSIONNUMBER);
  672. WriteWord(OLDMENUITEMTEMPLATEBYTESINHEADER);
  673. ParseOldMenu(FALSE, pRes);
  674. SaveResFile(pType, pRes);
  675. break;
  676. case (INT_PTR)RT_ICON:
  677. case (INT_PTR)RT_CURSOR:
  678. WriteFileInfo(pRes, pType, tokenbuf);
  679. pRes->size = GetFileName();
  680. if (pRes->size) {
  681. if (FileIsAnimated(pRes->size)) {
  682. goto ani;
  683. } else {
  684. pRes->size = GetIcon(pRes->size);
  685. SaveResFile(pType, pRes);
  686. }
  687. }
  688. break;
  689. case (INT_PTR) RT_ANIICON:
  690. case (INT_PTR) RT_ANICURSOR:
  691. ani:
  692. {
  693. USHORT iLastTypeOrd = pType->typeord;
  694. // Strictly speaking, ANIICON and ANICURSOR are not allowed. However,
  695. // we'll keep them around for the time being. BryanT 8/14/96.
  696. if ((pType->typeord == (USHORT)(INT_PTR)RT_ICON) ||
  697. (pType->typeord == (USHORT)(INT_PTR)RT_GROUP_ICON))
  698. {
  699. pType->typeord = (USHORT)(INT_PTR)RT_ANIICON;
  700. } else
  701. if ((pType->typeord == (USHORT)(INT_PTR) RT_CURSOR) ||
  702. (pType->typeord == (USHORT)(INT_PTR) RT_GROUP_CURSOR))
  703. {
  704. pType->typeord = (USHORT)(INT_PTR)RT_ANICURSOR;
  705. }
  706. WriteFileInfo(pRes, pType, tokenbuf);
  707. pRes->size = GetFileName();
  708. if (pRes->size) {
  709. pRes->size = GetAniIconsAniCursors(pRes->size);
  710. SaveResFile(pType, pRes);
  711. }
  712. pType->typeord = iLastTypeOrd;
  713. }
  714. break;
  715. case (INT_PTR)RT_BITMAP:
  716. WriteFileInfo(pRes, pType, tokenbuf);
  717. pRes->size = GetFileName();
  718. if (pRes->size) {
  719. /* Bitmap in DIB format */
  720. pRes ->size = GetNewBitmap();
  721. SaveResFile(pType, pRes);
  722. }
  723. break;
  724. case (INT_PTR)RT_GROUP_ICON:
  725. WriteFileInfo(pRes, pType, tokenbuf);
  726. pRes->size = GetFileName();
  727. if (pRes->size) {
  728. if (FileIsAnimated(pRes->size)) {
  729. goto ani;
  730. } else {
  731. if (fMacRsrcs)
  732. GetMacIcon(pType, pRes);
  733. else
  734. GetNewIconsCursors(pType, pRes, RT_ICON);
  735. }
  736. }
  737. break;
  738. case (INT_PTR)RT_GROUP_CURSOR:
  739. WriteFileInfo(pRes, pType, tokenbuf);
  740. pRes->size = GetFileName();
  741. if (pRes->size) {
  742. if (FileIsAnimated(pRes->size)) {
  743. goto ani;
  744. } else {
  745. if (fMacRsrcs)
  746. GetMacCursor(pType, pRes);
  747. else
  748. GetNewIconsCursors(pType, pRes, RT_CURSOR);
  749. }
  750. }
  751. break;
  752. case (INT_PTR)RT_FONT:
  753. WriteFileInfo(pRes, pType, tokenbuf);
  754. pRes->size = GetFileName();
  755. if (pRes->name)
  756. ParseError1(2143);
  757. if (AddFontRes(pRes)) {
  758. nFontsRead++;
  759. SaveResFile(pType, pRes);
  760. }
  761. break;
  762. case (INT_PTR)RT_FONTDIR:
  763. WriteFileInfo(pRes, pType, tokenbuf);
  764. fFontDirRead = TRUE;
  765. pRes->size = GetFileName();
  766. if (pRes->size) {
  767. SaveResFile(pType, pRes);
  768. }
  769. break;
  770. case (INT_PTR)RT_MESSAGETABLE:
  771. pRes->size = GetFileName();
  772. if (pRes->size) {
  773. SaveResFile(pType, pRes);
  774. }
  775. break;
  776. case (INT_PTR)RT_VERSION:
  777. VersionParse();
  778. SaveResFile(pType, pRes);
  779. break;
  780. case (INT_PTR)RT_DLGINCLUDE:
  781. DlgIncludeParse(pRes);
  782. SaveResFile(pType, pRes);
  783. break;
  784. case (INT_PTR)RT_TOOLBAR:
  785. GetToolbar(pRes);
  786. SaveResFile(pType, pRes);
  787. break;
  788. case (INT_PTR)RT_RCDATA:
  789. case (INT_PTR)RT_DLGINIT:
  790. default:
  791. if (token.type != BEGIN) {
  792. pRes->size = GetFileName();
  793. if (pRes->size) {
  794. WriteFileInfo(pRes, pType, tokenbuf);
  795. }
  796. } else {
  797. RESINFO_PARSE rip;
  798. bExternParse = FALSE;
  799. // Check to see if caller wants to parse this.
  800. if (lpfnParseCallback != NULL) {
  801. rip.size = 0L;
  802. rip.type = pType->type;
  803. rip.typeord = pType->typeord;
  804. rip.name = pRes->name;
  805. rip.nameord = pRes->nameord;
  806. rip.flags = pRes->flags;
  807. rip.language = pRes->language;
  808. rip.version = pRes->version;
  809. rip.characteristics = pRes->characteristics;
  810. bExternParse = (*lpfnParseCallback)(&rip, NULL, NULL);
  811. }
  812. if (!bExternParse) {
  813. GetRCData(pRes);
  814. } else {
  815. CONTEXTINFO_PARSE cip;
  816. CHAR mbuff[512]; // REVIEW: Long filenames?? See error.c also.
  817. extern PCHAR CodeArray;
  818. extern int CodeSize;
  819. extern int CCount;
  820. int nBegins = 1;
  821. int nCountSave; // CCount before END token reached
  822. cip.hHeap = hHeap;
  823. cip.hWndCaller = hWndCaller;
  824. cip.lpfnMsg = lpfnMessageCallback;
  825. cip.line = token.row;
  826. wsprintfA(mbuff, "%s(%%d) : %%s", curFile);
  827. cip.format = mbuff;
  828. // Collect data for caller to parse.
  829. while(nBegins > 0) {
  830. nCountSave = CCount;
  831. GetToken(FALSE);
  832. if (token.type == BEGIN)
  833. nBegins++;
  834. else if (token.type == END)
  835. nBegins--;
  836. }
  837. bExternParse = FALSE;
  838. if ((rip.size = nCountSave) > 0 &&
  839. !(*lpfnParseCallback)(&rip, (void **) &CodeArray, &cip)) {
  840. // Assume caller gave error message, and quit.
  841. quit("\n");
  842. }
  843. pRes->size = CCount = CodeSize = rip.size;
  844. }
  845. }
  846. SaveResFile(pType, pRes);
  847. break;
  848. }
  849. // write out end of new resource
  850. WriteResInfo(NULL, NULL, FALSE);
  851. }
  852. } while (token.type != EOFMARK);
  853. /* if we added fonts without a font directory, add one */
  854. if (!fFontDirRead && nFontsRead)
  855. AddFontDir();
  856. /* write string table */
  857. if (pResString != NULL)
  858. WriteTable(pResString);
  859. /* write Mac resource map */
  860. if (fMacRsrcs)
  861. WriteMacMap();
  862. CtlFree();
  863. if (fVerbose) {
  864. printf("\n");
  865. }
  866. return(errorCount == 0);
  867. }
  868. WORD
  869. GetLanguage()
  870. {
  871. WORD language;
  872. GetToken(FALSE);
  873. if (token.type != NUMLIT) {
  874. ParseError1(2144);
  875. return MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  876. }
  877. if (token.flongval) {
  878. ParseError1(2145);
  879. return MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  880. }
  881. language = token.val;
  882. GetToken(FALSE);
  883. if (token.type != COMMA) {
  884. ParseError1(2146);
  885. return MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  886. }
  887. GetToken(FALSE);
  888. if (token.type != NUMLIT) {
  889. ParseError1(2147);
  890. return MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  891. }
  892. if (token.flongval) {
  893. ParseError1(2148);
  894. return MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
  895. }
  896. return MAKELANGID(language, token.val);
  897. }