/*********************************************************************** * Microsoft (R) Windows (R) Resource Compiler * * Copyright (c) Microsoft Corporation. All rights reserved. * * File Comments: * * ***********************************************************************/ #include "rc.h" PRESINFO pResString = NULL; /* Used to add a stringtable */ /* at the end of processing if a stringtable */ /* was found. */ static PRCSTRING pSTHeader; /* Ptr to the start of the parsed STRINGTABLE. */ /*--------------------------------------------------------------------------*/ /* */ /* MyFAlloc() - */ /* */ /*--------------------------------------------------------------------------*/ void *MyFAlloc(size_t cb, const void *pv) { void *pvT= MyAlloc(cb); if (pv != NULL) { memmove(pvT, pv, cb); } else { memset(pvT, 0, cb); } return(pvT); } /*--------------------------------------------------------------------------*/ /* */ /* GetTable() - */ /* */ /*--------------------------------------------------------------------------*/ PRESINFO GetTable( PRESINFO pResTemp ) { PRCSTRING pCurrent; PRCSTRING pTrailer; CHAR bDone = FALSE; USHORT nStringID; PWCHAR p; PSYMINFO pCurrentSymbol; DWORD TmpSize; wchar_t *TmpBuf; int TmpRow; PreBeginParse(pResTemp, 2105); /* Does a string table already exist? */ if (pResString == NULL) { /* No, start at the beginning - otherwise append. */ pTrailer = (PRCSTRING)NULL; pSTHeader = (PRCSTRING)NULL; } do { pCurrent = pSTHeader; bDone = FALSE; if (token.type != NUMLIT) ParseError1(2149); //"Expected numeric constant in string table " nStringID = token.val; pCurrentSymbol = (SYMINFO*) MyFAlloc(sizeof(token.sym), (char*)&token.sym); if (!GetFullExpression(&nStringID, GFE_ZEROINIT | GFE_SHORT)) ParseError1(2110); //"Expected numeric constant in v table " if (token.type == COMMA) GetToken(TOKEN_NOEXPRESSION); if (token.type != LSTRLIT) ParseError1(2150); tokenbuf[token.val + 1] = 0; TmpSize = sizeof(WCHAR) * (token.val + 2); TmpBuf = (wchar_t *) MyFAlloc(TmpSize, tokenbuf); TmpRow = token.row; GetToken(TRUE); // wprintf(L"TmpSize: %d\tTmpBuf: %s\tTmpRow: %d\n", TmpSize, TmpBuf, TmpRow); while ((token.row == TmpRow) && (token.type == LSTRLIT)) { size_t NewSize = TmpSize + (sizeof(WCHAR) * (token.val)); wchar_t *NewBuf = (wchar_t *) MyAlloc(NewSize); memmove(NewBuf, TmpBuf, TmpSize); memmove((BYTE *) NewBuf + TmpSize-4, tokenbuf, (token.val * sizeof(WCHAR))); // wprintf(L"NewSize: %d\tNewBuf: %ws\ttoken.row: %d\ttokenbuf: %ws\n", NewSize, NewBuf, token.row, tokenbuf); MyFree(TmpBuf); TmpSize = NewSize; TmpBuf = NewBuf; GetToken(TRUE); } while (!bDone && pCurrent) { if (pCurrent->language == pResTemp->language) { if (pCurrent->hibits == (USHORT)(nStringID / BLOCKSIZE)) { bDone = TRUE; if (!(pCurrent->rgsz[nStringID % BLOCKSIZE])) { pCurrent->rgsz[nStringID % BLOCKSIZE] = TmpBuf; pCurrent->rgsym[nStringID % BLOCKSIZE] = pCurrentSymbol; } else { SET_MSG(2151, curFile, TmpRow, nStringID, pCurrent->rgsz[nStringID % BLOCKSIZE], TmpBuf ); ParseError3(2151); MyFree(TmpBuf); } TmpBuf = NULL; TmpSize = 0; } } pTrailer = pCurrent; pCurrent = pCurrent->next; } if (!bDone) { /* and thus pCurrent == NULL */ pCurrent = (PRCSTRING) MyFAlloc(sizeof(RCSTRING), NULL); pCurrent->hibits = (short)(nStringID / BLOCKSIZE); pCurrent->flags = pResTemp->flags; pCurrent->language = pResTemp->language; pCurrent->version = pResTemp->version; pCurrent->characteristics = pResTemp->characteristics; p = pCurrent->rgsz[nStringID%BLOCKSIZE] = TmpBuf; TmpBuf = NULL; TmpSize = 0; pCurrent->rgsym[nStringID%BLOCKSIZE] = pCurrentSymbol; if (pTrailer) pTrailer->next = pCurrent; if (!pSTHeader) pSTHeader = pCurrent; /* First time only */ } // GetToken(TRUE); } while (token.type != END); pResString = pResTemp; return pResString; } /*--------------------------------------------------------------------------*/ /* */ /* WriteTable() - */ /* */ /*--------------------------------------------------------------------------*/ VOID WriteTable( PRESINFO pResOld ) { PRCSTRING p; int i; PRESINFO pRes; PTYPEINFO pType; int n; PWCHAR s; UINT nBytesWritten; SYMINFO symInfo; /* Start at the start of the proper table. */ p = pSTHeader; while (p) { nBytesWritten = 0; CtlInit(); // 'STR#' resource starts with a count of strings if (fMacRsrcs) WriteWord(BLOCKSIZE); /* Write out the next block. */ for (i = 0; i < BLOCKSIZE; i++) { n = 0; s = p->rgsz[i]; if (fMacRsrcs) { WriteMacString(s, TRUE, TRUE); continue; } if (s) { while (s[n] || s[n + 1]) n++; // szsz terminated if (fAppendNull) n++; } nBytesWritten += sizeof(WCHAR) * (n + 1); WriteWord((WORD)n); while (n--) WriteWord(*s++); } pRes = (RESINFO * )MyAlloc(sizeof(RESINFO)); pRes->language = p->language; pRes->version = p->version; pRes->characteristics = p->characteristics; pType = AddResType(NULL, RT_STRING); pRes->size = nBytesWritten; /* Mark the resource as Moveable and Discardable. */ pRes->flags = p->flags; /*We're in an origin 1 world here*/ pRes->nameord = (short)(p->hibits + 1); SaveResFile(pType, pRes); memset(&symInfo, 0, sizeof(symInfo)); WriteResInfo(pRes, pType, FALSE); for (i=0; i < BLOCKSIZE; i++) { WriteSymbolUse(p->rgsym[i] != NULL && p->rgsz[i][0] != '\0' ? p->rgsym[i] : &symInfo); } WriteResInfo(NULL, NULL, FALSE); /* Move on to the next block. */ p = p->next; } } /*--------------------------------------------------------------------------*/ /* */ /* GetAccelerators() _ */ /* */ /*--------------------------------------------------------------------------*/ int GetAccelerators( PRESINFO pRes ) { int count = 0; int ntype; WCHAR c; int bTypeSpecified; RCACCEL Accel; PreBeginParse(pRes, 2106); do { if (token.type == END) continue; bTypeSpecified = FALSE; ntype = token.type; if (token.type == END) { MarkAccelFlagsByte(); WriteWord(0); WriteWord(0); WriteWord(0); WriteWord(0); count++; continue; } else if (token.type == NUMLIT) Accel.ascii = token.val; else if (token.type == LSTRLIT) { if (tokenbuf[0] == L'^') { if (wcslen(tokenbuf) != 2) ParseError1(2152); /* GetAccelerators() and support "^^" to put ^ */ if (tokenbuf[1] == L'^') Accel.ascii = L'^'; else { if (!iswalpha(c=towupper(tokenbuf[1]))) ParseError1(2154); Accel.ascii = c - L'A' + 1; } } else if (wcslen(tokenbuf) == 2) Accel.ascii = (WCHAR)((tokenbuf[0] << 8) + tokenbuf[1]); else if (wcslen(tokenbuf) == 1) Accel.ascii = tokenbuf[0]; else ParseError1(2155); } else ParseError1(2156); /* Get the trailing comma. */ GetToken(TRUE); if (token.type != COMMA) ParseError1(2157); /* Get the next number. */ GetToken(TRUE); if (token.type != NUMLIT) ParseError1(2107); Accel.id = token.val; WriteSymbolUse(&token.sym); if (!GetFullExpression(&Accel.id, GFE_ZEROINIT | GFE_SHORT)) ParseError1(2107); //"Expected numeric command value" Accel.flags = 0; if (token.type == COMMA) do { GetToken(TRUE); switch (token.type) { case TKVIRTKEY: Accel.flags |= fVIRTKEY; bTypeSpecified = TRUE; break; case TKASCII: bTypeSpecified = TRUE; break; /* don't set the flag */ case TKNOINVERT: Accel.flags |= fNOINVERT; break; case TKSHIFT: Accel.flags |= fSHIFT; break; case TKCONTROL: Accel.flags |= fCONTROL; break; case TKALT: Accel.flags |= fALT; break; default: ParseError1(2159); } GetToken(TRUE); } while (token.type == COMMA); if (ntype == NUMLIT && !bTypeSpecified) ParseError1(2163); if (!(Accel.flags & fVIRTKEY) && (Accel.flags & (fSHIFT | fCONTROL))) { SET_MSG(4203, curFile, token.row); SendError(Msg_Text); } if (Accel.flags & fVIRTKEY && ntype == LSTRLIT) { if (!iswalnum(Accel.ascii = (WCHAR)towupper(Accel.ascii))) { SET_MSG(4204, curFile, token.row); SendError(Msg_Text); } } MarkAccelFlagsByte(); WriteWord(Accel.flags); WriteWord(Accel.ascii); if (fMacRsrcs) { WriteLong(Accel.id); } else { WriteWord(Accel.id); WriteWord(0); } count++; } while (token.type != END); PatchAccelEnd(); return(5 * count); }