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.

405 lines
12 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* RCSTRING.C - */
  4. /* */
  5. /* StringTable and Accelerators Parsing Code */
  6. /* */
  7. /****************************************************************************/
  8. #include "rc.h"
  9. PRESINFO pResString = NULL; /* Used to add a stringtable */
  10. /* at the end of processing if a stringtable */
  11. /* was found. */
  12. static PRCSTRING pSTHeader;
  13. /* Ptr to the start of the parsed STRINGTABLE. */
  14. /*--------------------------------------------------------------------------*/
  15. /* */
  16. /* MyFAlloc() - */
  17. /* */
  18. /*--------------------------------------------------------------------------*/
  19. PCHAR
  20. MyFAlloc(
  21. UINT cb,
  22. PCHAR pb
  23. )
  24. {
  25. PCHAR pbT;
  26. pbT = (PCHAR)MyAlloc(cb);
  27. if (!pbT)
  28. quit("RC : fatal error RW1025: Out of heap memory");
  29. if (pb) {
  30. memmove(pbT, pb, cb);
  31. } else {
  32. memset(pbT, 0, cb);
  33. }
  34. return pbT;
  35. }
  36. /*--------------------------------------------------------------------------*/
  37. /* */
  38. /* GetTable() - */
  39. /* */
  40. /*--------------------------------------------------------------------------*/
  41. PRESINFO
  42. GetTable(
  43. PRESINFO pResTemp
  44. )
  45. {
  46. PRCSTRING pCurrent;
  47. PRCSTRING pTrailer;
  48. CHAR bDone = FALSE;
  49. USHORT nStringID;
  50. PWCHAR p;
  51. PSYMINFO pCurrentSymbol;
  52. DWORD TmpSize;
  53. PCHAR TmpBuf;
  54. int TmpRow;
  55. PreBeginParse(pResTemp, 2105);
  56. /* Does a string table already exist? */
  57. if (pResString == NULL) {
  58. /* No, start at the beginning - otherwise append. */
  59. pTrailer = (PRCSTRING)NULL;
  60. pSTHeader = (PRCSTRING)NULL;
  61. }
  62. do {
  63. pCurrent = pSTHeader;
  64. bDone = FALSE;
  65. if (token.type != NUMLIT)
  66. ParseError1(2149); //"Expected numeric constant in string table "
  67. nStringID = token.val;
  68. pCurrentSymbol = (SYMINFO*)MyFAlloc(sizeof(token.sym), (char*)&token.sym);
  69. if (!GetFullExpression(&nStringID, GFE_ZEROINIT | GFE_SHORT))
  70. ParseError1(2110); //"Expected numeric constant in v table "
  71. if (token.type == COMMA)
  72. GetToken(TOKEN_NOEXPRESSION);
  73. if (token.type != LSTRLIT)
  74. ParseError1(2150);
  75. tokenbuf[token.val + 1] = 0;
  76. TmpSize = sizeof(WCHAR) * (token.val + 2);
  77. TmpBuf = MyFAlloc(TmpSize, (PCHAR)tokenbuf);
  78. TmpRow = token.row;
  79. GetToken(TRUE);
  80. // printf("TmpSize: %d\tTmpBuf: %ws\tTmpRow: %d\n", TmpSize, TmpBuf, TmpRow);
  81. while ((token.row == TmpRow) && (token.type == LSTRLIT)) {
  82. ULONG NewSize = TmpSize + (sizeof(WCHAR) * (token.val));
  83. PCHAR NewBuf = (PCHAR)MyAlloc(NewSize);
  84. if (!NewBuf)
  85. quit("RC : fatal error RW1025: Out of heap memory");
  86. memmove(NewBuf, TmpBuf, TmpSize);
  87. memmove(NewBuf+TmpSize-4, tokenbuf, (token.val * sizeof(WCHAR)));
  88. // printf("NewSize: %d\tNewBuf: %ws\ttoken.row: %d\ttokenbuf: %ws\n", NewSize, NewBuf, token.row, tokenbuf);
  89. MyFree(TmpBuf);
  90. TmpSize = NewSize;
  91. TmpBuf = NewBuf;
  92. GetToken(TRUE);
  93. }
  94. while (!bDone && pCurrent) {
  95. if (pCurrent->language == pResTemp->language) {
  96. if (pCurrent->hibits == (USHORT)(nStringID / BLOCKSIZE)) {
  97. bDone = TRUE;
  98. if (!(pCurrent->rgsz[nStringID % BLOCKSIZE])) {
  99. pCurrent->rgsz[nStringID % BLOCKSIZE] = (PWCHAR) TmpBuf;
  100. pCurrent->rgsym[nStringID % BLOCKSIZE] = pCurrentSymbol;
  101. }
  102. else {
  103. SET_MSG(Msg_Text, sizeof(Msg_Text),
  104. GET_MSG(2151),
  105. curFile,
  106. TmpRow,
  107. nStringID,
  108. pCurrent->rgsz[nStringID % BLOCKSIZE],
  109. TmpBuf
  110. );
  111. ParseError3(2151);
  112. MyFree(TmpBuf);
  113. }
  114. TmpBuf = NULL; TmpSize = 0;
  115. }
  116. }
  117. pTrailer = pCurrent;
  118. pCurrent = pCurrent->next;
  119. }
  120. if (!bDone) { /* and thus pCurrent == (PCHAR)NULL */
  121. pCurrent = (PRCSTRING)MyFAlloc(
  122. sizeof(RCSTRING), (PCHAR)NULL);
  123. pCurrent->hibits = (short)(nStringID / BLOCKSIZE);
  124. pCurrent->flags = pResTemp->flags;
  125. pCurrent->language = pResTemp->language;
  126. pCurrent->version = pResTemp->version;
  127. pCurrent->characteristics = pResTemp->characteristics;
  128. p = pCurrent->rgsz[nStringID%BLOCKSIZE] = (PWCHAR)TmpBuf;
  129. TmpBuf = NULL; TmpSize = 0;
  130. pCurrent->rgsym[nStringID%BLOCKSIZE] = pCurrentSymbol;
  131. if (pTrailer)
  132. pTrailer->next = pCurrent;
  133. if (!pSTHeader)
  134. pSTHeader = pCurrent; /* First time only */
  135. }
  136. // GetToken(TRUE);
  137. } while (token.type != END);
  138. pResString = pResTemp;
  139. return pResString;
  140. }
  141. /*--------------------------------------------------------------------------*/
  142. /* */
  143. /* WriteTable() - */
  144. /* */
  145. /*--------------------------------------------------------------------------*/
  146. VOID
  147. WriteTable(
  148. PRESINFO pResOld
  149. )
  150. {
  151. PRCSTRING p;
  152. int i;
  153. PRESINFO pRes;
  154. PTYPEINFO pType;
  155. int n;
  156. PWCHAR s;
  157. UINT nBytesWritten;
  158. SYMINFO symInfo;
  159. /* Start at the start of the proper table. */
  160. p = pSTHeader;
  161. while (p) {
  162. nBytesWritten = 0;
  163. CtlInit();
  164. // 'STR#' resource starts with a count of strings
  165. if (fMacRsrcs)
  166. WriteWord(BLOCKSIZE);
  167. /* Write out the next block. */
  168. for (i = 0; i < BLOCKSIZE; i++) {
  169. n = 0;
  170. s = p->rgsz[i];
  171. if (fMacRsrcs) {
  172. WriteMacString(s, TRUE, TRUE);
  173. continue;
  174. }
  175. if (s) {
  176. while (s[n] || s[n + 1])
  177. n++; // szsz terminated
  178. if (fAppendNull)
  179. n++;
  180. }
  181. nBytesWritten += sizeof(WCHAR) * (n + 1);
  182. WriteWord((WORD)n);
  183. while (n--)
  184. WriteWord(*s++);
  185. }
  186. pRes = (RESINFO * )MyAlloc(sizeof(RESINFO));
  187. pRes->language = p->language;
  188. pRes->version = p->version;
  189. pRes->characteristics = p->characteristics;
  190. pType = AddResType(NULL, RT_STRING);
  191. pRes->size = nBytesWritten;
  192. /* Mark the resource as Moveable and Discardable. */
  193. pRes->flags = p->flags;
  194. /*We're in an origin 1 world here*/
  195. pRes->nameord = (short)(p->hibits + 1);
  196. SaveResFile(pType, pRes);
  197. memset(&symInfo, 0, sizeof(symInfo));
  198. WriteResInfo(pRes, pType, FALSE);
  199. for (i=0; i < BLOCKSIZE; i++) {
  200. WriteSymbolUse(p->rgsym[i] != NULL && p->rgsz[i][0] != '\0' ? p->rgsym[i] : &symInfo);
  201. }
  202. WriteResInfo(NULL, NULL, FALSE);
  203. /* Move on to the next block. */
  204. p = p->next;
  205. }
  206. }
  207. /*--------------------------------------------------------------------------*/
  208. /* */
  209. /* GetAccelerators() _ */
  210. /* */
  211. /*--------------------------------------------------------------------------*/
  212. int
  213. GetAccelerators(
  214. PRESINFO pRes
  215. )
  216. {
  217. int count = 0;
  218. int ntype;
  219. WCHAR c;
  220. int bTypeSpecified;
  221. RCACCEL Accel;
  222. PreBeginParse(pRes, 2106);
  223. do {
  224. if (token.type == END)
  225. continue;
  226. bTypeSpecified = FALSE;
  227. ntype = token.type;
  228. if (token.type == END) {
  229. MarkAccelFlagsByte();
  230. WriteWord(0);
  231. WriteWord(0);
  232. WriteWord(0);
  233. WriteWord(0);
  234. count++;
  235. continue;
  236. }
  237. else if (token.type == NUMLIT)
  238. Accel.ascii = token.val;
  239. else if (token.type == LSTRLIT) {
  240. if (tokenbuf[0] == L'^') {
  241. if (wcslen(tokenbuf) != 2)
  242. ParseError1(2152);
  243. /* GetAccelerators() and support "^^" to put ^ */
  244. if (tokenbuf[1] == L'^')
  245. Accel.ascii = L'^';
  246. else {
  247. if (!iswalpha(c=towupper(tokenbuf[1])))
  248. ParseError1(2154);
  249. Accel.ascii = c - L'A' + 1;
  250. }
  251. }
  252. else if (wcslen(tokenbuf) == 2)
  253. Accel.ascii = (WCHAR)((tokenbuf[0] << 8) + tokenbuf[1]);
  254. else if (wcslen(tokenbuf) == 1)
  255. Accel.ascii = tokenbuf[0];
  256. else
  257. ParseError1(2155);
  258. }
  259. else
  260. ParseError1(2156);
  261. /* Get the trailing comma. */
  262. GetToken(TRUE);
  263. if (token.type != COMMA)
  264. ParseError1(2157);
  265. /* Get the next number. */
  266. GetToken(TRUE);
  267. if (token.type != NUMLIT)
  268. ParseError1(2107);
  269. Accel.id = token.val;
  270. WriteSymbolUse(&token.sym);
  271. if (!GetFullExpression(&Accel.id, GFE_ZEROINIT | GFE_SHORT))
  272. ParseError1(2107); //"Expected numeric command value"
  273. Accel.flags = 0;
  274. if (token.type == COMMA)
  275. do {
  276. GetToken(TRUE);
  277. switch (token.type) {
  278. case TKVIRTKEY:
  279. Accel.flags |= fVIRTKEY;
  280. bTypeSpecified = TRUE;
  281. break;
  282. case TKASCII:
  283. bTypeSpecified = TRUE;
  284. break; /* don't set the flag */
  285. case TKNOINVERT:
  286. Accel.flags |= fNOINVERT;
  287. break;
  288. case TKSHIFT:
  289. Accel.flags |= fSHIFT;
  290. break;
  291. case TKCONTROL:
  292. Accel.flags |= fCONTROL;
  293. break;
  294. case TKALT:
  295. Accel.flags |= fALT;
  296. break;
  297. default:
  298. ParseError1(2159);
  299. }
  300. GetToken(TRUE);
  301. } while (token.type == COMMA);
  302. if (ntype == NUMLIT && !bTypeSpecified)
  303. ParseError1(2163);
  304. if (!(Accel.flags & fVIRTKEY) && (Accel.flags & (fSHIFT | fCONTROL))) {
  305. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(4203), curFile, token.row);
  306. SendError(Msg_Text);
  307. }
  308. if (Accel.flags & fVIRTKEY && ntype == LSTRLIT) {
  309. if (!iswalnum(Accel.ascii = (WCHAR)towupper(Accel.ascii))) {
  310. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(4204), curFile, token.row);
  311. SendError(Msg_Text);
  312. }
  313. }
  314. MarkAccelFlagsByte();
  315. WriteWord(Accel.flags);
  316. WriteWord(Accel.ascii);
  317. if (fMacRsrcs) {
  318. WriteLong(Accel.id);
  319. } else {
  320. WriteWord(Accel.id);
  321. WriteWord(0);
  322. }
  323. count++;
  324. } while (token.type != END);
  325. PatchAccelEnd();
  326. return(5 * count);
  327. }