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.

502 lines
13 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* rcutil.C - */
  4. /* */
  5. /* Windows 3.0 Resource Compiler - Utility Functions */
  6. /* */
  7. /* */
  8. /****************************************************************************/
  9. #include "rc.h"
  10. /*---------------------------------------------------------------------------*/
  11. /* */
  12. /* MyAlloc() - */
  13. /* */
  14. /*---------------------------------------------------------------------------*/
  15. // HACK Alert. Allocate an extra longlong and return past it (to allow for PREVCH()
  16. // to store a byte before the allocation block and to maintain 8 byte alignment).
  17. VOID *
  18. MyAlloc(
  19. UINT nbytes
  20. )
  21. {
  22. PVOID s;
  23. if ((s = HeapAlloc(hHeap, HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY, nbytes+8)) != NULL) {
  24. return(((PCHAR)s)+8);
  25. } else {
  26. SET_MSG(Msg_Text, sizeof(Msg_Text), GET_MSG(1120), nbytes);
  27. quit(Msg_Text);
  28. }
  29. return NULL;
  30. }
  31. /*---------------------------------------------------------------------------*/
  32. /* */
  33. /* MyFree() - */
  34. /* */
  35. /*---------------------------------------------------------------------------*/
  36. VOID *
  37. MyFree(
  38. VOID *p
  39. )
  40. {
  41. if (p) {
  42. HeapFree(hHeap, HEAP_NO_SERIALIZE, ((PCHAR)p)-8);
  43. }
  44. return(NULL);
  45. }
  46. /*---------------------------------------------------------------------------*/
  47. /* */
  48. /* MyMakeStr() - */
  49. /* */
  50. /*---------------------------------------------------------------------------*/
  51. WCHAR *
  52. MyMakeStr(
  53. WCHAR *s
  54. )
  55. {
  56. WCHAR * s1;
  57. if (s) {
  58. s1 = (WCHAR *) MyAlloc((wcslen(s) + 1) * sizeof(WCHAR)); /* allocate buffer */
  59. wcscpy(s1, s); /* copy string */
  60. } else {
  61. s1 = s;
  62. }
  63. return(s1);
  64. }
  65. /*---------------------------------------------------------------------------*/
  66. /* */
  67. /* MyRead() - */
  68. /* */
  69. /*---------------------------------------------------------------------------*/
  70. UINT
  71. MyRead(
  72. FILE *fh,
  73. VOID *p,
  74. UINT n
  75. )
  76. {
  77. UINT n1;
  78. n1 = fread(p, 1, (size_t)n, fh);
  79. if (ferror (fh)) {
  80. quit(GET_MSG(1121));
  81. return 0;
  82. } else {
  83. return(n1);
  84. }
  85. }
  86. /*---------------------------------------------------------------------------*/
  87. /* */
  88. /* MyWrite() - */
  89. /* */
  90. /*---------------------------------------------------------------------------*/
  91. UINT
  92. MyWrite(
  93. FILE *fh,
  94. VOID *p,
  95. UINT n
  96. )
  97. {
  98. UINT n1;
  99. if ((n1 = fwrite(p, 1, n, fh)) != n) {
  100. quit("RC : fatal error RW1022: I/O error writing file.");
  101. return (0);
  102. } else {
  103. return(n1);
  104. }
  105. }
  106. /*---------------------------------------------------------------------------*/
  107. /* */
  108. /* MyAlign() - */
  109. /* */
  110. /*---------------------------------------------------------------------------*/
  111. UINT
  112. MyAlign(
  113. PFILE fh
  114. )
  115. {
  116. DWORD t0 = 0;
  117. DWORD ib;
  118. /* align file to dword */
  119. ib = MySeek(fh, 0L, SEEK_CUR);
  120. if (ib % 4) {
  121. ib = 4 - ib % 4;
  122. MyWrite(fh, (PVOID)&t0, (UINT)ib);
  123. return(ib);
  124. }
  125. return(0);
  126. }
  127. /*---------------------------------------------------------------------------*/
  128. /* */
  129. /* MySeek() - */
  130. /* */
  131. /*---------------------------------------------------------------------------*/
  132. LONG
  133. MySeek(
  134. FILE *fh,
  135. LONG pos,
  136. int cmd
  137. )
  138. {
  139. if (fseek(fh, pos, cmd))
  140. quit("RC : fatal error RW1023: I/O error seeking in file");
  141. if ((pos = ftell (fh)) == -1L)
  142. quit("RC : fatal error RW1023: I/O error seeking in file");
  143. return(pos);
  144. }
  145. /*---------------------------------------------------------------------------*/
  146. /* */
  147. /* MyCopy() - */
  148. /* */
  149. /*---------------------------------------------------------------------------*/
  150. int
  151. MyCopy(
  152. FILE *srcfh,
  153. PFILE dstfh,
  154. ULONG nbytes
  155. )
  156. {
  157. PCHAR buffer = (PCHAR) MyAlloc(BUFSIZE);
  158. UINT n;
  159. while (nbytes) {
  160. if (nbytes <= BUFSIZE)
  161. n = (UINT)nbytes;
  162. else
  163. n = BUFSIZE;
  164. nbytes -= n;
  165. MyRead(srcfh, buffer, n);
  166. MyWrite( dstfh, buffer, n);
  167. }
  168. MyFree(buffer);
  169. return(n);
  170. }
  171. /*---------------------------------------------------------------------------*/
  172. /* */
  173. /* MyCopyAll() - */
  174. /* */
  175. /*---------------------------------------------------------------------------*/
  176. int
  177. MyCopyAll(
  178. FILE *srcfh,
  179. PFILE dstfh
  180. )
  181. {
  182. PCHAR buffer = (PCHAR) MyAlloc(BUFSIZE);
  183. UINT n;
  184. while ((n = fread(buffer, 1, BUFSIZE, srcfh)) != 0)
  185. MyWrite(dstfh, buffer, n);
  186. MyFree(buffer);
  187. return TRUE;
  188. }
  189. /*---------------------------------------------------------------------------*/
  190. /* */
  191. /* strpre() - */
  192. /* */
  193. /*---------------------------------------------------------------------------*/
  194. /* strpre: return -1 if pch1 is a prefix of pch2, 0 otherwise.
  195. * compare is case insensitive.
  196. */
  197. int
  198. strpre(
  199. PWCHAR pch1,
  200. PWCHAR pch2
  201. )
  202. {
  203. while (*pch1) {
  204. if (!*pch2)
  205. return 0;
  206. else if (towupper(*pch1) == towupper(*pch2))
  207. pch1++, pch2++;
  208. else
  209. return 0;
  210. }
  211. return - 1;
  212. }
  213. /*---------------------------------------------------------------------------*/
  214. /* */
  215. /* iswhite() - */
  216. /* */
  217. /*---------------------------------------------------------------------------*/
  218. int
  219. iswhite (
  220. WCHAR c
  221. )
  222. {
  223. /* returns true for whitespace and linebreak characters */
  224. switch (c) {
  225. case L' ':
  226. case L'\t':
  227. case L'\r':
  228. case L'\n':
  229. case EOF:
  230. return(-1);
  231. break;
  232. default:
  233. return(0);
  234. break;
  235. }
  236. }
  237. /*---------------------------------------------------------------------------*/
  238. /* */
  239. /* IsSwitchChar() - */
  240. /* */
  241. /*---------------------------------------------------------------------------*/
  242. BOOL
  243. IsSwitchChar(
  244. CHAR c
  245. )
  246. {
  247. /* true for switch characters */
  248. return (c == '/' || c == '-');
  249. }
  250. /*---------------------------------------------------------------------------*/
  251. /* */
  252. /* searchenv() - */
  253. /* */
  254. /*---------------------------------------------------------------------------*/
  255. /* the _searchenv() function in the C5.0 RTL doesn't work. In particular,
  256. * it fails to check for \ characters and can end up returning paths like
  257. * D:\\FILE.EXT. szActual is assumed to be at least MAX_PATH and will
  258. * always get walked all over
  259. */
  260. VOID
  261. searchenv(
  262. PCHAR szFile,
  263. PCHAR szVar,
  264. PCHAR szActual
  265. )
  266. {
  267. PCHAR pchVar;
  268. PCHAR pch;
  269. int ich;
  270. PFILE fhTemp;
  271. if (!strcmp(szVar, "INCLUDE"))
  272. pchVar = pchInclude;
  273. else
  274. pchVar = getenv(szVar);
  275. if (!pchVar)
  276. return;
  277. /* we don't do absolute paths */
  278. if (szFile[0] == '\\' || szFile[0] == '/' || szFile[1] == ':') {
  279. for (ich = 0; szActual[ich] = szFile[ich]; ich++)
  280. ;
  281. return;
  282. }
  283. do {
  284. /* copy the next environment string... */
  285. for (ich = 0; (szActual[ich] = pchVar[ich]) != '\000'; ich++)
  286. if (pchVar[ich] == ';')
  287. break;
  288. szActual[ich] = '\000';
  289. pchVar += ich;
  290. if (*pchVar)
  291. pchVar++;
  292. /* HARD LOOP -- find end of path string */
  293. for (pch = szActual; *pch; pch++)
  294. ;
  295. /* check first! this is what _searchenv() messed up! */
  296. if (pch[-1] != '\\' && pch[-1] != '/')
  297. *pch++ = '\\';
  298. /* HARD LOOP -- we already know szFile does start with a drive or abs. dir */
  299. for (ich = 0; pch[ich] = szFile[ich]; ich++)
  300. ;
  301. /* is the file here? szActual already contains name */
  302. if ((fhTemp = fopen(szActual, "rb")) != NULL) {
  303. fclose (fhTemp);
  304. return;
  305. }
  306. } while (szActual[0] && *pchVar);
  307. /* if we reach here, we know szActual is empty */
  308. return;
  309. }
  310. /*---------------------------------------------------------------------------*/
  311. /* */
  312. /* ExtractFileName(szFullName, szFileName) - */
  313. /* */
  314. /* This routine is used to extract just the file name from a string */
  315. /* that may or may not contain a full or partial path name. */
  316. /* */
  317. /*---------------------------------------------------------------------------*/
  318. VOID
  319. ExtractFileName(
  320. PWCHAR szFullName,
  321. PWCHAR szFileName
  322. )
  323. {
  324. int iLen;
  325. PWCHAR pCh;
  326. iLen = wcslen(szFullName);
  327. /* Goto the last character of the full name; */
  328. pCh = (PWCHAR)(szFullName + iLen);
  329. pCh--;
  330. /* Look for '/', '\\' or ':' character */
  331. while (iLen--) {
  332. if ((*pCh == L'\\') || (*pCh == L'/') || (*pCh == L':'))
  333. break;
  334. pCh--;
  335. }
  336. wcscpy(szFileName, ++pCh);
  337. }
  338. DWORD
  339. wcsatoi(
  340. WCHAR *s
  341. )
  342. {
  343. DWORD t = 0;
  344. while (*s) {
  345. t = 10 * t + (DWORD)((CHAR)*s - '0');
  346. s++;
  347. }
  348. return t;
  349. }
  350. WCHAR *
  351. wcsitow(
  352. LONG v,
  353. WCHAR *s,
  354. DWORD r
  355. )
  356. {
  357. DWORD cb = 0;
  358. DWORD t;
  359. DWORD tt = v;
  360. while (tt) {
  361. t = tt % r;
  362. cb++;
  363. tt /= r;
  364. }
  365. s += cb;
  366. *s-- = 0;
  367. while (v) {
  368. t = v % r;
  369. *s-- = (WCHAR)((CHAR)t + '0');
  370. v /= r;
  371. }
  372. return ++s;
  373. }
  374. // ----------------------------------------------------------------------------
  375. //
  376. // PreBeginParse
  377. //
  378. // ----------------------------------------------------------------------------
  379. VOID
  380. PreBeginParse(
  381. PRESINFO pRes,
  382. int id
  383. )
  384. {
  385. while (token.type != BEGIN) {
  386. switch (token.type) {
  387. case TKLANGUAGE:
  388. pRes->language = GetLanguage();
  389. break;
  390. case TKVERSION:
  391. GetToken(FALSE);
  392. if (token.type != NUMLIT)
  393. ParseError1(2139);
  394. pRes->version = token.longval;
  395. break;
  396. case TKCHARACTERISTICS:
  397. GetToken(FALSE);
  398. if (token.type != NUMLIT)
  399. ParseError1(2140);
  400. pRes->characteristics = token.longval;
  401. break;
  402. default:
  403. ParseError1(id);
  404. break;
  405. }
  406. GetToken(FALSE);
  407. }
  408. if (token.type != BEGIN)
  409. ParseError1(id);
  410. GetToken(TRUE);
  411. }