/****************************************************************************/ /* */ /* rcx.C - AFX symbol info writer */ /* */ /* Windows 3.5 Resource Compiler */ /* */ /****************************************************************************/ #include "rc.h" ///////////////////////////////////////////////////////////////////////////// // Symbol information static PFILE fhFileMap = NULL; static LONG lFileMap = 0; static PFILE fhResMap = NULL; static LONG lResMap = 0; static PFILE fhRefMap = NULL; static LONG lRefMap = 0; static PFILE fhSymList = NULL; static LONG lSymList = 0; static LONG HdrOffset; static CHAR szEndOfResource[2] = {'$', '\000'}; #if 0 static WCHAR szPrevFile[255]; // for symbol definitions #endif static CHAR szSymList[_MAX_PATH]; static CHAR szFileMap[_MAX_PATH]; static CHAR szRefMap[_MAX_PATH]; static CHAR szResMap[_MAX_PATH]; static WCHAR szName[] = L"HWB"; #define OPEN_FLAGS (_O_TRUNC | _O_BINARY | _O_CREAT | _O_RDWR) #define PROT_FLAGS (S_IWRITE | S_IWRITE) void wtoa(WORD value, char* string, int radix) { if (value == (WORD)-1) _itoa(-1, string, radix); else _itoa(value, string, radix); } int ConvertAndWrite(PFILE fp, PWCHAR pwch) { int n; char szMultiByte[_MAX_PATH]; // assumes _MAX_PATH >= MAX_SYMBOL n = wcslen(pwch) + 1; n = WideCharToMultiByte(uiCodePage, 0, pwch, n, szMultiByte, MAX_PATH, NULL, NULL); return MyWrite(fp, (PVOID)szMultiByte, n); } VOID WriteResHdr (FILE *fh, LONG size, WORD id) { LONG val; /* add data size and header size */ MyWrite(fh, (PVOID)&size, sizeof(ULONG)); // will backpatch MyWrite(fh, (PVOID)&HdrOffset, sizeof(ULONG)); /* add type and name */ MyWrite(fh, (PVOID)szName, sizeof(szName)); val = 0xFFFF; MyWrite(fh, (PVOID)&val, sizeof(WORD)); MyWrite(fh, (PVOID)&id, sizeof(WORD)); MyAlign(fh); /* add data struct version, flags, language, resource data version /* and characteristics */ val = 0; MyWrite(fh, (PVOID)&val, sizeof(ULONG)); val = 0x0030; MyWrite(fh, (PVOID)&val, sizeof(WORD)); MyWrite(fh, (PVOID)&language, sizeof(WORD)); val = 2; MyWrite(fh, (PVOID)&val, sizeof(ULONG)); MyWrite(fh, (PVOID)&characteristics, sizeof(ULONG)); } BOOL InitSymbolInfo() { PCHAR szTmp; if (!fAFXSymbols) return(TRUE); #if 0 szPrevFile[0] = L'\0'; #endif if ((szTmp = _tempnam(NULL, "RCX1")) != NULL) strcpy(szSymList, szTmp); else strcpy(szSymList, tmpnam(NULL)); if ((szTmp = _tempnam(NULL, "RCX2")) != NULL) strcpy(szFileMap, szTmp); else strcpy(szFileMap, tmpnam(NULL)); if ((szTmp = _tempnam(NULL, "RCX3")) != NULL) strcpy(szRefMap, szTmp); else strcpy(szRefMap, tmpnam(NULL)); if ((szTmp = _tempnam(NULL, "RCX4")) != NULL) strcpy(szResMap, szTmp); else strcpy(szResMap, tmpnam(NULL)); if (!(fhFileMap = fopen(szFileMap, "w+b")) || !(fhSymList = fopen(szSymList, "w+b")) || !(fhRefMap = fopen(szRefMap, "w+b")) || !(fhResMap = fopen(szResMap, "w+b"))) return FALSE; /* calculate header size */ HdrOffset = sizeof(szName); HdrOffset += 2 * sizeof(WORD); if (HdrOffset % 4) HdrOffset += sizeof(WORD); // could only be off by 2 HdrOffset += sizeof(RESADDITIONAL); WriteResHdr(fhSymList, lSymList, 200); WriteResHdr(fhFileMap, lFileMap, 201); WriteResHdr(fhRefMap, lRefMap, 202); WriteResHdr(fhResMap, lResMap, 2); return TRUE; } BOOL TermSymbolInfo(PFILE fhResFile) { long lStart; PTYPEINFO pType; RESINFO r; if (!fAFXSymbols) return(TRUE); if (fhResFile == NULL_FILE) goto termCloseOnly; WriteSymbolDef(L"", L"", L"", 0, (char)0); MySeek(fhSymList, 0L, SEEK_SET); MyWrite(fhSymList, (PVOID)&lSymList, sizeof(lSymList)); MySeek(fhFileMap, 0L, SEEK_SET); MyWrite(fhFileMap, (PVOID)&lFileMap, sizeof(lFileMap)); WriteResInfo(NULL, NULL, FALSE); MySeek(fhRefMap, 0L, SEEK_SET); MyWrite(fhRefMap, (PVOID)&lRefMap, sizeof(lRefMap)); // now append these to .res pType = AddResType(L"HWB", 0); r.flags = 0x0030; r.name = NULL; r.next = NULL; r.language = language; r.version = version; r.characteristics = characteristics; MySeek(fhSymList, 0L, SEEK_SET); MyAlign(fhResFile); r.BinOffset = MySeek(fhResFile, 0L, SEEK_END) + HdrOffset; r.size = lSymList; r.nameord = 200; WriteResInfo(&r, pType, TRUE); MyCopyAll(fhSymList, fhResFile); MySeek(fhFileMap, 0L, SEEK_SET); MyAlign(fhResFile); r.BinOffset = MySeek(fhResFile, 0L, SEEK_END) + HdrOffset; r.size = lFileMap; r.nameord = 201; WriteResInfo(&r, pType, TRUE); MyCopyAll(fhFileMap, fhResFile); MySeek(fhRefMap, 0L, SEEK_SET); MyAlign(fhResFile); r.BinOffset = MySeek(fhResFile, 0L, SEEK_END) + HdrOffset; r.size = lRefMap; r.nameord = 202; WriteResInfo(&r, pType, TRUE); MyCopyAll(fhRefMap, fhResFile); MyAlign(fhResFile); lStart = MySeek(fhResFile, 0L, SEEK_CUR); MySeek(fhResMap, 0L, SEEK_SET); MyWrite(fhResMap, (PVOID)&lResMap, sizeof(lResMap)); MySeek(fhResMap, 0L, SEEK_SET); MyCopyAll(fhResMap, fhResFile); // patch the HWB:1 resource with HWB:2's starting point MySeek(fhResFile, lOffIndex, SEEK_SET); MyWrite(fhResFile, (PVOID)&lStart, sizeof(lStart)); MySeek(fhResFile, 0L, SEEK_END); termCloseOnly:; if (fhFileMap) { fclose(fhFileMap); remove(szFileMap); } if (fhRefMap) { fclose(fhRefMap); remove(szRefMap); } if (fhSymList) { fclose(fhSymList); remove(szSymList); } if (fhResMap) { fclose(fhResMap); remove(szResMap); } return TRUE; } void WriteSymbolUse(PSYMINFO pSym) { if (!fAFXSymbols) return; if (pSym == NULL) { WORD nID = (WORD)-1; lRefMap += MyWrite(fhRefMap, (PVOID)&szEndOfResource, sizeof(szEndOfResource)); lRefMap += MyWrite(fhRefMap, (PVOID)&nID, sizeof(nID)); } else { lRefMap += ConvertAndWrite(fhRefMap, pSym->name); lRefMap += MyWrite(fhRefMap, (PVOID)&pSym->nID, sizeof(pSym->nID)); } } void WriteSymbolDef(PWCHAR name, PWCHAR value, PWCHAR file, WORD line, char flags) { if (!fAFXSymbols) return; if (name[0] == L'$' && value[0] != L'\0') { RESINFO res; TYPEINFO typ; res.nameord = (USHORT) -1; res.language = language; typ.typeord = (USHORT) -1; WriteFileInfo(&res, &typ, value); return; } lSymList += ConvertAndWrite(fhSymList, name); lSymList += ConvertAndWrite(fhSymList, value); #if 0 if (wcscmp(szPrevFile, file) == 0) { lSymList += MyWrite(fhSymList, (PVOID)"", sizeof(CHAR)); } else { wcscpy(szPrevFile, file); lSymList += ConvertAndWrite(fhSymList, file); } #endif lSymList += MyWrite(fhSymList, (PVOID)&line, sizeof(line)); lSymList += MyWrite(fhSymList, (PVOID)&flags, sizeof(flags)); } void WriteFileInfo(PRESINFO pRes, PTYPEINFO pType, PWCHAR szFileName) { WORD n1 = 0xFFFF; if (!fAFXSymbols) return; if (pType->typeord == 0) lFileMap += MyWrite(fhFileMap, (PVOID)pType->type, (wcslen(pType->type) + 1) * sizeof(WCHAR)); else { WORD n2 = pType->typeord; if (n2 == (WORD)RT_MENUEX) n2 = (WORD)RT_MENU; else if (n2 == (WORD)RT_DIALOGEX) n2 = (WORD)RT_DIALOG; lFileMap += MyWrite(fhFileMap, (PVOID)&n1, sizeof(WORD)); lFileMap += MyWrite(fhFileMap, (PVOID)&n2, sizeof(WORD)); } if (pRes->nameord == 0) lFileMap += MyWrite(fhFileMap, (PVOID)pRes->name, (wcslen(pRes->name) + 1) * sizeof(WCHAR)); else { lFileMap += MyWrite(fhFileMap, (PVOID)&n1, sizeof(WORD)); lFileMap += MyWrite(fhFileMap, (PVOID)&pRes->nameord, sizeof(WORD)); } lFileMap += MyWrite(fhFileMap, (PVOID)&pRes->language, sizeof(WORD)); lFileMap += MyWrite(fhFileMap, (PVOID)szFileName, (wcslen(szFileName) + 1) * sizeof(WCHAR)); } void WriteResInfo(PRESINFO pRes, PTYPEINFO pType, BOOL bWriteMapEntry) { if (!fAFXSymbols) return; if (pRes == NULL) { WORD nID = (WORD)-1; //assert(bWriteMapEntry == FALSE); lRefMap += MyWrite(fhRefMap, (PVOID)&szEndOfResource, sizeof(szEndOfResource)); lRefMap += MyWrite(fhRefMap, (PVOID)&nID, sizeof(nID)); return; } if (bWriteMapEntry) { WORD n1 = 0xFFFF; ULONG t0 = 0; /* add data size and data offset */ lResMap += MyWrite(fhResMap, (PVOID)&pRes->size, sizeof(ULONG)); lResMap += MyWrite(fhResMap, (PVOID)&pRes->BinOffset, sizeof(ULONG)); /* Is this an ordinal type? */ if (pType->typeord) { WORD n2 = pType->typeord; if (n2 == (WORD)RT_MENUEX) n2 = (WORD)RT_MENU; else if (n2 == (WORD)RT_DIALOGEX) n2 = (WORD)RT_DIALOG; lResMap += MyWrite(fhResMap, (PVOID)&n1, sizeof(WORD)); lResMap += MyWrite(fhResMap, (PVOID)&n2, sizeof(WORD)); } else lResMap += MyWrite(fhResMap, (PVOID)pType->type, (wcslen(pType->type) + 1) * sizeof(WCHAR)); if (pRes->nameord) { lResMap += MyWrite(fhResMap, (PVOID)&n1, sizeof(WORD)); lResMap += MyWrite(fhResMap, (PVOID)&pRes->nameord, sizeof(WORD)); } else lResMap += MyWrite(fhResMap, (PVOID)pRes->name, (wcslen(pRes->name) + 1) * sizeof(WCHAR)); lResMap += MyAlign(fhResMap); /* add data struct version, flags, language, resource data version /* and characteristics */ lResMap += MyWrite(fhResMap, (PVOID)&t0, sizeof(ULONG)); lResMap += MyWrite(fhResMap, (PVOID)&pRes->flags, sizeof(WORD)); lResMap += MyWrite(fhResMap, (PVOID)&pRes->language, sizeof(WORD)); lResMap += MyWrite(fhResMap, (PVOID)&pRes->version, sizeof(ULONG)); lResMap += MyWrite(fhResMap, (PVOID)&pRes->characteristics, sizeof(ULONG)); return; } if (pType->typeord == 0) { lRefMap += ConvertAndWrite(fhRefMap, pType->type); } else { char szID[33]; WORD n2 = pType->typeord; if (n2 == (WORD)RT_MENUEX) n2 = (WORD)RT_MENU; else if (n2 == (WORD)RT_DIALOGEX) n2 = (WORD)RT_DIALOG; wtoa(n2, szID, 10); lRefMap += MyWrite(fhRefMap, (PVOID)szID, strlen(szID)+1); } if (pRes->nameord == 0) lRefMap += ConvertAndWrite(fhRefMap, pRes->name); else { char szID[33]; wtoa(pRes->nameord, szID, 10); lRefMap += MyWrite(fhRefMap, (PVOID)szID, strlen(szID)+1); } lRefMap += ConvertAndWrite(fhRefMap, pRes->sym.name); lRefMap += ConvertAndWrite(fhRefMap, pRes->sym.file); lRefMap += MyWrite(fhRefMap,(PVOID)&pRes->sym.line,sizeof(pRes->sym.line)); } /*---------------------------------------------------------------------------*/ /* */ /* AfxGetChar() - */ /* */ /* Same as OurGetChar function but does not treat semicolon as comment char */ /* */ /*---------------------------------------------------------------------------*/ int AfxGetChar() { WCHAR nextChar; nextChar = LitChar (); return((int)nextChar); } /*---------------------------------------------------------------------------*/ /* */ /* GetSymbolDef() - get a symbol def record and write out info */ /* */ /*---------------------------------------------------------------------------*/ void GetSymbolDef(int fReportError, WCHAR curChar) { SYMINFO sym; WCHAR szDefn[_MAX_PATH]; WCHAR szLine[16]; PWCHAR p; CHAR flags = 0; WCHAR currentChar = curChar; if (!fAFXSymbols) return; currentChar = AfxGetChar(); // get past SYMDEFSTART /* read the symbol name */ p = sym.name; while ((*p++ = currentChar) != SYMDELIMIT) currentChar = AfxGetChar(); *--p = L'\0'; if (p - sym.name > MAX_SYMBOL) { ParseError1(2247); return; } currentChar = AfxGetChar(); /* read past the delimiter */ p = szDefn; while ((*p++ = currentChar) != SYMDELIMIT) currentChar = AfxGetChar(); *--p = L'\0'; currentChar = AfxGetChar(); /* read past the delimiter */ #if 0 p = sym.file; while ((*p++ = currentChar) != SYMDELIMIT) currentChar = AfxGetChar(); *--p = L'\0'; currentChar = AfxGetChar(); /* read past the delimiter */ #else sym.file[0] = L'\0'; #endif p = szLine; while ((*p++ = currentChar) != SYMDELIMIT) currentChar = AfxGetChar(); *--p = L'\0'; sym.line = (WORD)wcsatoi(szLine); currentChar = AfxGetChar(); /* read past the delimiter */ flags = (CHAR)currentChar; flags &= 0x7f; // clear the hi bit currentChar = AfxGetChar(); /* read past the delimiter */ /* leave positioned at last character (LitChar will bump) */ if (currentChar != SYMDELIMIT) { ParseError1(2248); } WriteSymbolDef(sym.name, szDefn, sym.file, sym.line, flags); } /*---------------------------------------------------------------------------*/ /* */ /* GetSymbol() - read a symbol and put id in the token if there */ /* */ /*---------------------------------------------------------------------------*/ void GetSymbol(int fReportError, WCHAR curChar) { WCHAR currentChar = curChar; token.sym.name[0] = L'\0'; token.sym.file[0] = L'\0'; token.sym.line = 0; if (!fAFXSymbols) return; /* skip whitespace */ while (iswhite(currentChar)) currentChar = AfxGetChar(); if (currentChar == SYMUSESTART) { WCHAR * p; int i = 0; WCHAR szLine[16]; currentChar = AfxGetChar(); // get past SYMUSESTART if (currentChar != L'\"') { ParseError1(2249); return; } currentChar = AfxGetChar(); // get past the first \" /* read the symbol name */ p = token.sym.name; while ((*p++ = currentChar) != SYMDELIMIT) currentChar = AfxGetChar(); *--p = L'\0'; if (p - token.sym.name > MAX_SYMBOL) { ParseError1(2247); return; } currentChar = AfxGetChar(); /* read past the delimiter */ p = token.sym.file; while ((*p++ = currentChar) != SYMDELIMIT) currentChar = AfxGetChar(); *--p = L'\0'; currentChar = AfxGetChar(); /* read past the delimiter */ p = szLine; while ((*p++ = currentChar) != L'\"') currentChar = AfxGetChar(); *--p = L'\0'; token.sym.line = (WORD)wcsatoi(szLine); if (currentChar != L'\"') { ParseError1(2249); return; } currentChar = AfxGetChar(); // get past SYMDELIMIT /* skip whitespace */ while (iswhite(currentChar)) currentChar = AfxGetChar(); } }