STDMETHODIMP CTextLexer::SetInput (PCWSTR pszInput, long iLen) { HRESULT hr; // Release anything we already have if (m_pszInput != NULL) VSFree (m_pszInput); for (long i=0; i<m_arrayTokens.Count(); i++) { if (m_arrayTokens[i].HasOverhead()) { VSFree (m_arrayTokens[i].Overhead()); } } m_arrayTokens.ClearAll(); m_arrayLines.ClearAll(); m_fTokenized = FALSE; m_hr = S_OK; // If iLen is -1, use the null-terminated length if (iLen == -1) iLen = (long)wcslen (pszInput); // Copy the text, ensuring that it's null-terminated m_pszInput = (PWSTR)VSAlloc ((iLen + 1) * sizeof (WCHAR)); if (m_pszInput == NULL) return E_OUTOFMEMORY; memcpy (m_pszInput, pszInput, iLen * sizeof (WCHAR)); m_pszInput[iLen] = 0; long *piLine; // Establish the first entry in the line table if (FAILED (hr = m_arrayLines.Add (NULL, &piLine))) return hr; *piLine = 0; // Start the input stream for tokenization m_pszCurrent = m_pszCurLine = m_pszInput; m_iCurLine = 0; TOKENID tok = TID_INVALID; CSTOKEN *pToken; // Scan the text while (tok != TID_ENDFILE && !FAILED (m_hr)) { if (FAILED (hr = m_arrayTokens.Add (NULL, &pToken))) return hr; tok = ScanToken (pToken); } // That's it! If we didn't fail, signal ourselves as being tokenized if (!FAILED (m_hr)) m_fTokenized = TRUE; return m_hr; }
void *CTextLexer::TokenMemAlloc (CSTOKEN *pToken, size_t iSize) { // Each token for which extra space is allocated must be (is) placed in our // array of tokens, which we are responsible for cleaning up during our // destruction. return VSAlloc (iSize); }
// // Search the binary tree and add the given string // return true if it was added or false if it already // exists // HRESULT ConsoleArgs::TreeAdd(b_tree **root, LPCWSTR add) { // Special case - init the tree if it // doesn't already exist if (*root == NULL) { *root = MakeLeaf(add); return *root == NULL ? E_OUTOFMEMORY : S_OK; } size_t name_len = wcslen(add)+1; LPWSTR szCopy = (LPWSTR)VSAlloc(name_len * sizeof(WCHAR)); if (!szCopy) { m_output->ShowErrorId (FTL_NoMemory, ERROR_FATAL); return NULL; } HRESULT hr = StringCchCopyW (szCopy, name_len, add); ASSERT (SUCCEEDED (hr)); // otherwise, just let the template do the work hr = (*root)->Add(szCopy, _wcsicmp); if (hr != S_OK) // S_FALSE means it already existed VSFree(szCopy); return hr; }
// Copy an argument list into an argv array. The argv array is allocated, the // arguments themselves are not allocated -- just pointer copied. bool ConsoleArgs::GetArgs( int * pargc, WCBuffer ** pargv) { LPWSTR cmdLine = GetCommandLineW(); *pargc = 0; *pargv = NULL; TextToArgs(cmdLine, &m_listArgs); if (m_output->HadFatalError()) return false; if (m_listArgs) { // make prefix happy... // Strip the process name VSFree(m_listArgs->arg); WStrList * listProc = m_listArgs; m_listArgs = m_listArgs->next; delete listProc; } #ifdef CLIENT_IS_CSC // Process '/noconfig', and CSC.CFG, modifying the argument list ProcessAutoConfig(); #endif // Process Response Files ProcessResponseArgs(); if (m_output->HadError()) return false; // Now convert to an argc/argv form for remaining processing. int argc = 0; for (WStrList * listCurArg = m_listArgs; listCurArg != NULL; listCurArg = listCurArg->next) { if (listCurArg->arg) ++argc; } m_rgArgs = (WCBuffer *)VSAlloc(sizeof(WCBuffer) * (argc)); if (!m_rgArgs) { m_output->ShowErrorId (FTL_NoMemory, ERROR_FATAL); return false; } int i = 0; for (WStrList * listCurArg = m_listArgs; listCurArg != NULL; listCurArg = listCurArg->next) { if (listCurArg->arg) m_rgArgs[i++] = WCBuffer::CreateFrom(listCurArg->arg); } *pargc = argc; *pargv = m_rgArgs; return !m_output->HadError(); }
void *CScanLexer::TokenMemAlloc (CSTOKEN *pToken, size_t iSize) { if (SizeAdd(iSize, m_iMemUsed) > (size_t)m_iMemSize) { size_t iRoundSize = SizeAdd(m_iMemUsed + iSize, 0x100) & ~(size_t)0xff; // Hard-coded growth by 256 byte blocks void *pMem = (m_pTokenMem == NULL) ? VSAlloc (iRoundSize) : VSRealloc (m_pTokenMem, iRoundSize); if (pMem == NULL) return NULL; m_pTokenMem = pMem; m_iMemSize = iRoundSize; } ASSERT (SizeAdd(m_iMemUsed, iSize) <= (size_t)m_iMemSize); void *pRet = ((BYTE *)m_pTokenMem + m_iMemUsed); m_iMemUsed += iSize; return pRet; }
// // Create a simple leaf tree node with the given text // b_tree * ConsoleArgs::MakeLeaf(LPCWSTR text) { b_tree * t = NULL; size_t name_len = wcslen(text)+1; LPWSTR szCopy = (LPWSTR)VSAlloc(name_len * sizeof(WCHAR)); if (!szCopy) { m_output->ShowErrorId (FTL_NoMemory, ERROR_FATAL); return NULL; } HRESULT hr; hr = StringCchCopyW (szCopy, name_len, text); ASSERT (SUCCEEDED (hr)); t = new b_tree(szCopy); if (!t) { VSFree(szCopy); m_output->ShowErrorId (FTL_NoMemory, ERROR_FATAL); return NULL; } return t; }
void CStringBuilder::Append (PCWSTR pszText, size_t iLen) { // Do nothing if we've already failed if (FAILED (m_hr)) return; // If -1, use nul to determine length if (iLen == (size_t)-1) iLen = wcslen (pszText); // Determine new size and reallocate if necessary size_t iReqSize = (m_iLen + iLen + m_iAllocSize) & (~(m_iAllocSize -1)); if (m_pszText == m_szBuf) { if (iReqSize > (sizeof (m_szBuf) / sizeof (m_szBuf[0]))) { // The size needed is bigger than our static buffer. Time to allocate // the dynamic buffer for the first time m_pszText = (PWSTR)VSAlloc (iReqSize * sizeof (WCHAR)); if (m_pszText == NULL) { m_hr = E_OUTOFMEMORY; m_pszText = m_szBuf; return; } // Copy the current text wcscpy (m_pszText, m_szBuf); // Keep our current pointer current... m_pszCur = m_pszText + m_iLen; ASSERT (m_pszCur[0] == 0); } else { // Do nothing -- the text will fit in our static buffer. } } else if (iReqSize != ((m_iLen + m_iAllocSize) & (~(m_iAllocSize - 1)))) { // See if we need to increase our allocation size if (iReqSize >= 0x10000 && m_iAllocSize < 0x10000) { m_iAllocSize = 0x10000; iReqSize = ((m_iLen + iLen + m_iAllocSize) & (~(m_iAllocSize - 1))); } else if (iReqSize >= 0x1000 && m_iAllocSize < 0x1000) { m_iAllocSize = 0x1000; iReqSize = ((m_iLen + iLen + m_iAllocSize) & (~(m_iAllocSize - 1))); } // Need to grow PWSTR pszNewText = (PWSTR)VSRealloc (m_pszText, iReqSize * sizeof (WCHAR)); if (pszNewText == NULL) { m_hr = E_OUTOFMEMORY; return; } m_pszText = pszNewText; // Keep our current pointer current... m_pszCur = m_pszText + m_iLen; ASSERT (m_pszCur[0] == 0); } ASSERT (iReqSize > m_iLen + iLen); // Copy incoming text to end of buffer. wcsncpy (m_pszCur, pszText, iLen); m_iLen += iLen; m_pszCur += iLen; m_pszCur[0] = 0; }
// // Process Auto Config options: // #1 search for '/noconfig' // if not present and csc.cfg exists in EXE dir, inject after env var stuff // void ConsoleArgs::ProcessAutoConfig() { bool fFoundNoConfig = false; // Scan the argument list for the "/noconfig" options. If present, just kill it and bail. for (WStrList * listArgCur = m_listArgs; listArgCur; listArgCur = listArgCur->next) { // Skip everything except options WCHAR * szArg = listArgCur->arg; if (szArg == NULL || (szArg[0] != '/' && szArg[0] != '-')) continue; if (_wcsicmp(szArg + 1, L"noconfig") == 0) { listArgCur->arg = NULL; VSFree(szArg); // We found it, empty it but keep checking in case they specified it twice fFoundNoConfig = true; } } if (fFoundNoConfig) return; // If we got here it means there was no '/noconfig' WCHAR szPath[MAX_PATH]; if (W_IsUnicodeSystem()) { if(!GetModuleFileNameW(NULL, szPath, lengthof(szPath))) szPath[0] = 0; } else { CHAR szTemp[MAX_PATH]; if (!GetModuleFileNameA(NULL, szTemp, lengthof(szTemp)) || !MultiByteToWideChar( AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, szTemp, -1, szPath, lengthof(szPath))) szPath[0] = 0; } if (*szPath && PathRemoveFileSpecW(szPath) && PathAppendW(szPath, L"csc.rsp")) { if (W_Access( szPath, 4) == 0) { // We know the file exists and that we have read access // so add into the list size_t cchLen = wcslen(szPath) + 2; // +2 for @ and terminator WCHAR * szPathCopy = (WCHAR*)VSAlloc( sizeof(WCHAR) * cchLen); if (!szPathCopy || FAILED(StringCchCopyW(szPathCopy + 1, cchLen, szPath))) { VSFAIL("The string changed size, or our pointers got messed up"); m_output->ShowErrorId(FTL_NoMemory, ERROR_FATAL); return; } szPathCopy[0] = L'@'; WStrList * listArgNew = new WStrList( szPathCopy, m_listArgs); if (!listArgNew) { VSFree(szPathCopy); m_output->ShowErrorId(FTL_NoMemory, ERROR_FATAL); return; } m_listArgs = listArgNew; } } }
// // Parse the text into a list of argument // return the total count // and set 'args' to point to the last list element's 'next' // This function assumes the text is NULL terminated // void ConsoleArgs::TextToArgs(LPCWSTR szText, WStrList ** listReplace) { WStrList **argLast; const WCHAR *pCur; size_t iSlash; int iCount; argLast = listReplace; pCur = szText; iCount = 0; // Guaranteed that all tokens are no bigger than the entire file. LPWSTR szTemp = (LPWSTR)VSAlloc(sizeof(WCHAR) * (wcslen(szText) + 1)); if (!szTemp) { m_output->ShowErrorId (FTL_NoMemory, ERROR_FATAL); return; } while (*pCur != '\0') { WCHAR *pPut, *pFirst, *pLast; WCHAR chIllegal; LEADINGWHITE: while (IsWhitespace( *pCur) && *pCur != '\0') pCur++; if (*pCur == '\0') break; else if (*pCur == L'#') { while ( *pCur != '\0' && *pCur != '\n') pCur++; // Skip to end of line goto LEADINGWHITE; } int cQuotes = 0; pPut = pFirst = szTemp; chIllegal = 0; while ((!IsWhitespace( *pCur) || !!(cQuotes & 1)) && *pCur != '\0') { switch (*pCur) { // All this weird slash stuff follows the standard argument processing routines case L'\\': iSlash = 0; // Copy and advance while counting slashes while (*pCur == L'\\') { *pPut++ = *pCur++; iSlash++; } // Slashes not followed by a quote character don't matter now if (*pCur != L'\"') break; // If there's an odd count of slashes, it's escaping the quote // Otherwise the quote is a quote if ((iSlash & 1) == 0) { ++cQuotes; } *pPut++ = *pCur++; break; case L'\"': ++cQuotes; *pPut++ = *pCur++; break; case L'\x01': case L'\x02': case L'\x03': case L'\x04': case L'\x05': case L'\x06': case L'\x07': case L'\x08': case L'\x09': case L'\x0A': case L'\x0B': case L'\x0C': case L'\x0D': case L'\x0E': case L'\x0F': case L'\x10': case L'\x11': case L'\x12': case L'\x13': case L'\x14': case L'\x15': case L'\x16': case L'\x17': case L'\x18': case L'\x19': case L'\x1A': case L'\x1B': case L'\x1C': case L'\x1D': case L'\x1E': case L'\x1F': case L'|': // Save the first legal character and skip over them if (chIllegal == 0) chIllegal = *pCur; pCur++; break; default: *pPut++ = *pCur++; // Copy the char and advance break; } } pLast = pPut; *pPut++ = '\0'; // If the string is surrounded by quotes, with no interior quotes, remove them. if (cQuotes == 2 && *pFirst == L'\"' && *(pLast - 1) == L'\"') { ++pFirst; --pLast; *pLast = L'\0'; } if (chIllegal != 0) { m_output->ShowErrorIdString( ERR_IllegalOptionChar, ERROR_ERROR, chIllegal, pFirst); } size_t cchLen = pLast - pFirst + 1; WCHAR * szArgCopy = (WCHAR*)VSAlloc( sizeof(WCHAR) * cchLen); if (!szArgCopy || FAILED(StringCchCopyW(szArgCopy, cchLen, pFirst))) { VSFAIL("The string changed size, or our pointers got messed up"); m_output->ShowErrorId(FTL_NoMemory, ERROR_FATAL); break; } WStrList * listArgNew = new WStrList( szArgCopy, (*argLast)); if (!listArgNew) { m_output->ShowErrorId(FTL_NoMemory, ERROR_FATAL); break; } *argLast = listArgNew; argLast = &listArgNew->next; } VSFree(szTemp); }