bool GLCgShader::SetTexture(const str_type::string& name, TextureWeakPtr pTexture) { if (m_focus != Shader::SF_PIXEL) { ShowMessage("Shader::SetTexture - textures can't be set as vertex shader parameter", GSMT_ERROR); return false; } CGparameter param = SeekParameter(name, m_params); if (!param) return ShowInvalidParameterWarning(m_shaderName, name); DisableIfEnabled(param); const GLTexture* textureObj = (GLTexture*)(pTexture.lock().get()); cgGLSetTextureParameter(param, textureObj->GetTextureInfo().m_texture); if (CheckForError("Shader::SetTexture", m_shaderName)) return false; cgGLEnableTextureParameter(param); if (CheckForError("Shader::SetTexture", m_shaderName)) return false; // add this param to the enabled texture parameter list so we can disable it with DisableTetureParams m_enabledTextures.push_back(param); return true; }
bool CZipArchive::CloseNewFile() { if (m_iFileOpened != compress) { TRACE(_T("A new file must be opened.\n")); return false; } m_info.m_stream.avail_in = 0; int err = Z_OK; if (CurrentFile()->m_uMethod == Z_DEFLATED) while (err == Z_OK) { if (m_info.m_stream.avail_out == 0) { m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false); m_info.m_uComprLeft = 0; m_info.m_stream.avail_out = m_info.m_pBuffer.GetSize(); m_info.m_stream.next_out = (unsigned char*)(char*)m_info.m_pBuffer; } DWORD uTotal = m_info.m_stream.total_out; err = deflate(&m_info.m_stream, Z_FINISH); m_info.m_uComprLeft += m_info.m_stream.total_out - uTotal; } if (err == Z_STREAM_END) err = Z_OK; CheckForError(err); if (m_info.m_uComprLeft > 0) m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false); if (CurrentFile()->m_uMethod == Z_DEFLATED) { err = deflateEnd(&m_info.m_stream); CheckForError(err); } CurrentFile()->m_uComprSize = m_info.m_stream.total_out; CurrentFile()->m_uUncomprSize = m_info.m_stream.total_in; m_centralDir.CloseNewFile(); m_iFileOpened = nothing; m_info.m_pBuffer.Release(); return true; }
// seek wxFileOffset wxFile::Seek(wxFileOffset ofs, wxSeekMode mode) { wxASSERT_MSG( IsOpened(), wxT("can't seek on closed file") ); wxCHECK_MSG( ofs != wxInvalidOffset || mode != wxFromStart, wxInvalidOffset, wxT("invalid absolute file offset") ); int origin; switch ( mode ) { default: wxFAIL_MSG(wxT("unknown seek origin")); case wxFromStart: origin = SEEK_SET; break; case wxFromCurrent: origin = SEEK_CUR; break; case wxFromEnd: origin = SEEK_END; break; } wxFileOffset iRc = wxSeek(m_fd, ofs, origin); if ( CheckForError(iRc) ) { wxLogSysError(_("can't seek on file descriptor %d"), m_fd); } return iRc; }
bool GLCgShader::SetShader() { cgGLBindProgram(m_cgProgam); if (CheckForError("cgGLBindProgram", m_shaderName)) return false; cgUpdateProgramParameters(m_cgProgam); if (CheckForError("cgUpdateProgramParameters", m_shaderName)) return false; cgGLEnableProfile(m_cgProfile); if (CheckForError("cgGLEnableProfile", m_shaderName)) return false; return true; }
GLCgShaderContext::GLCgShaderContext() : m_cgContext(0) { m_cgContext = cgCreateContext(); CheckForError("GLCgShaderContext creating the context"); cgSetParameterSettingMode(m_cgContext, CG_DEFERRED_PARAMETER_SETTING); CheckForError("GLCgShaderContext setting parameter mode"); #ifdef DEBUG cgGLSetDebugMode(CG_TRUE); #else cgGLSetDebugMode(CG_FALSE); #endif m_latestFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); m_latestVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); }
bool GLCgShader::SetConstant(const str_type::string& name, const math::Vector2 &v) { CGparameter param = SeekParameter(name, m_params); if (!param) return ShowInvalidParameterWarning(m_shaderName, name); cgSetParameter2fv(param, (float*)&v); if (CheckForError("Shader::SetConstant2F setting parameter", m_shaderName)) return false; return true; }
bool GLCgShader::SetConstant(const str_type::string& name, const int n) { CGparameter param = SeekParameter(name, m_params); if (!param) return ShowInvalidParameterWarning(m_shaderName, name); cgSetParameter1i(param, n); if (CheckForError("Shader::SetConstant1I setting parameter", m_shaderName)) return false; return true; }
void CDeflateCompressor::InitDecompression(CZipFileHeader* pFile, CZipCryptograph* pCryptograph) { CBaseLibCompressor::InitDecompression(pFile, pCryptograph); if (m_pFile->m_uMethod == methodDeflate) { SetOpaque(&m_stream.opaque, &m_options); CheckForError(zarch_inflateInit2_(&m_stream, -MAX_WBITS, ZLIB_VERSION, sizeof(zarch_z_stream))); } m_stream.total_out = 0; m_stream.avail_in = 0; }
bool GLCgShader::SetMatrixConstant(const str_type::string& name, const math::Matrix4x4 &matrix) { CGparameter param = SeekParameter(name, m_params); if (!param) return ShowInvalidParameterWarning(m_shaderName, name); cgSetMatrixParameterfr(param, (float*)&matrix); if (CheckForError("Shader::SetMatrixConstant setting parameter", m_shaderName)) return false; return true; }
bool GLCgShader::SetConstantArray(const str_type::string& name, unsigned int nElements, const boost::shared_array<const math::Vector2>& v) { CGparameter param = SeekParameter(name, m_params); if (!param) return ShowInvalidParameterWarning(m_shaderName, name); cgGLSetParameterArray2f(param, 0, (long)nElements, (float*)v.get()); if (CheckForError("Shader::SetConstantArrayF setting parameter", m_shaderName)) return false; return true; }
// get current file offset wxFileOffset wxFile::Tell() const { wxASSERT( IsOpened() ); wxFileOffset iRc = wxTell(m_fd); if ( CheckForError(iRc) ) { wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd); } return iRc; }
GLuint GLES2ShaderContext::CreateProgramFromCurrentShaders() { std::stringstream ss; ss << m_currentVS->GetShaderName() << "(" << m_currentVS->GetShader() << ") / " << m_currentPS->GetShaderName() << " (" << m_currentPS->GetShader() << ")"; const str_type::string programName = ss.str(); const GLuint program = glCreateProgram(); if (program) { glAttachShader(program, m_currentVS->GetShader()); CheckForError(programName + " glAttachShader (vertex)"); glAttachShader(program, m_currentPS->GetShader()); CheckForError(programName + " glAttachShader (pixel)"); glLinkProgram(program); GLint linkStatus = GL_FALSE; glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); if (linkStatus != GL_TRUE) { m_logger.Log(programName + ": link failed", Platform::FileLogger::ERROR); GLint bufLength = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); if (bufLength) { char* buf = new char [bufLength]; if (buf) { glGetProgramInfoLog(program, bufLength, NULL, buf); m_logger.Log(str_type::string("could not link program: ") + programName + buf, Platform::FileLogger::ERROR); delete [] buf; } } glDeleteProgram(program); return 0; } } return program; }
void CDeflateCompressor::FinishCompression(bool bAfterException) { m_stream.avail_in = 0; if (!bAfterException) { if (m_pFile->m_uMethod == methodDeflate) { int err; do { if (m_stream.avail_out == 0) { FlushWriteBuffer(); m_stream.avail_out = m_pBuffer.GetSize(); m_stream.next_out = (zarch_Bytef*)(char*)m_pBuffer; } ZIP_SIZE_TYPE uTotal = m_stream.total_out; err = zarch_deflate(&m_stream, Z_FINISH); m_uComprLeft += m_stream.total_out - uTotal; } while (err == Z_OK); if (err == Z_STREAM_END) err = Z_OK; CheckForError(err); if (m_uComprLeft > 0) FlushWriteBuffer(); CheckForError(zarch_deflateEnd(&m_stream)); } // it may be increased by the encrypted header size in CZipFileHeader::PrepareData m_pFile->m_uComprSize += m_stream.total_out; m_pFile->m_uUncomprSize = m_stream.total_in; } EmptyPtrList(); ReleaseBuffer(); }
// open the file bool wxFile::Open(const wxString& fileName, OpenMode mode, int accessMode) { int flags = O_BINARY; switch ( mode ) { case read: flags |= O_RDONLY; break; case write_append: if ( wxFile::Exists(fileName) ) { flags |= O_WRONLY | O_APPEND; break; } //else: fall through as write_append is the same as write if the // file doesn't exist wxFALLTHROUGH; case write: flags |= O_WRONLY | O_CREAT | O_TRUNC; break; case write_excl: flags |= O_WRONLY | O_CREAT | O_EXCL; break; case read_write: flags |= O_RDWR; break; } #ifdef __WINDOWS__ // only read/write bits for "all" are supported by this function under // Windows, and VC++ 8 returns EINVAL if any other bits are used in // accessMode, so clear them as they have at best no effect anyhow accessMode &= wxS_IRUSR | wxS_IWUSR; #endif // __WINDOWS__ int fildes = wxOpen( fileName, flags, accessMode); if ( CheckForError(fildes) ) { wxLogSysError(_("can't open file '%s'"), fileName); return false; } Attach(fildes); return true; }
// read ssize_t wxFile::Read(void *pBuf, size_t nCount) { wxCHECK( (pBuf != NULL) && IsOpened(), 0 ); ssize_t iRc = wxRead(m_fd, pBuf, nCount); if ( CheckForError(iRc) ) { wxLogSysError(_("can't read from file descriptor %d"), m_fd); return wxInvalidOffset; } return iRc; }
// write size_t wxFile::Write(const void *pBuf, size_t nCount) { wxCHECK( (pBuf != NULL) && IsOpened(), 0 ); ssize_t iRc = wxWrite(m_fd, pBuf, nCount); if ( CheckForError(iRc) ) { wxLogSysError(_("can't write to file descriptor %d"), m_fd); iRc = 0; } return iRc; }
bool GLCgShader::CreateCgProgram() { DestroyCgProgram(); m_cgProgam = cgCreateProgram( m_cgContext, CG_SOURCE, m_shaderCode.c_str(), m_cgProfile, m_entry.empty() ? NULL : m_entry.c_str(), NULL); if (CheckForError("Shader::LoadShader creating program from file", m_shaderName)) return false; // compile shader cgGLLoadProgram(m_cgProgam); if (CheckForError("GS_SHADER::CompileShader loading the program", m_shaderName)) return false; FillParameters(CG_GLOBAL); FillParameters(CG_PROGRAM); return true; }
bool CZipArchive::WriteNewFile(void *pBuf, DWORD iSize) { if (m_iFileOpened != compress) { TRACE(_T("A new file must be opened.\n")); return false; } m_info.m_stream.next_in = (unsigned char*)pBuf; m_info.m_stream.avail_in = iSize; CurrentFile()->m_uCrc32 = crc32(CurrentFile()->m_uCrc32, (unsigned char*)pBuf, iSize); while (m_info.m_stream.avail_in > 0) { if (m_info.m_stream.avail_out == 0) { m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false); m_info.m_uComprLeft = 0; m_info.m_stream.avail_out = m_info.m_pBuffer.GetSize(); m_info.m_stream.next_out = (unsigned char*)(char*)m_info.m_pBuffer; } if (CurrentFile()->m_uMethod == Z_DEFLATED) { DWORD uTotal = m_info.m_stream.total_out; int err = deflate(&m_info.m_stream, Z_NO_FLUSH); CheckForError(err); m_info.m_uComprLeft += m_info.m_stream.total_out - uTotal; } else { DWORD uToCopy = (m_info.m_stream.avail_in < m_info.m_stream.avail_out) ? m_info.m_stream.avail_in : m_info.m_stream.avail_out; memcpy(m_info.m_stream.next_out, m_info.m_stream.next_in, uToCopy); m_info.m_stream.avail_in -= uToCopy; m_info.m_stream.avail_out -= uToCopy; m_info.m_stream.next_in += uToCopy; m_info.m_stream.next_out += uToCopy; m_info.m_stream.total_in += uToCopy; m_info.m_stream.total_out += uToCopy; m_info.m_uComprLeft += uToCopy; } } return true; }
// close bool wxFile::Close() { if ( IsOpened() ) { if ( CheckForError(wxClose(m_fd)) ) { wxLogSysError(_("can't close file descriptor %d"), m_fd); m_fd = fd_invalid; return false; } else m_fd = fd_invalid; } return true; }
// flush bool wxFile::Flush() { #ifdef HAVE_FSYNC // fsync() only works on disk files and returns errors for pipes, don't // call it then if ( IsOpened() && GetKind() == wxFILE_KIND_DISK ) { if ( CheckForError(wxFsync(m_fd)) ) { wxLogSysError(_("can't flush file descriptor %d"), m_fd); return false; } } #endif // HAVE_FSYNC return true; }
// create the file, fail if it already exists and bOverwrite bool wxFile::Create(const wxString& fileName, bool bOverwrite, int accessMode) { // if bOverwrite we create a new file or truncate the existing one, // otherwise we only create the new file and fail if it already exists int fd = wxOpen( fileName, O_BINARY | O_WRONLY | O_CREAT | (bOverwrite ? O_TRUNC : O_EXCL), accessMode ); if ( CheckForError(fd) ) { wxLogSysError(_("can't create file '%s'"), fileName); return false; } Attach(fd); return true; }
bool GLCgShader::LoadShaderFromString( ShaderContextPtr context, const str_type::string& shaderName, const std::string& codeAsciiString, const SHADER_FOCUS focus, const SHADER_PROFILE profile, const char *entry) { if (entry) m_entry = entry; m_shaderCode = codeAsciiString; m_cgContext = ExtractCgContext(context); m_shaderName = shaderName; m_focus = focus; m_profile = profile; if (focus == Shader::SF_PIXEL) { //CGprofile latestProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); m_cgProfile = CG_PROFILE_ARBFP1; } else { #ifdef MACOSX m_cgProfile = CG_PROFILE_ARBVP1; #else m_cgProfile = cgGLGetLatestProfile(CG_GL_VERTEX); #endif } cgGLSetOptimalOptions(m_cgProfile); if (CheckForError("Shader::LoadShader setting optimal options", m_shaderName)) return false; if (CreateCgProgram()) { m_video->InsertRecoverableResource(this); } else { return false; } return true; }
bool CZipArchive::OpenFile(WORD uIndex) { if (!m_centralDir.IsValidIndex(uIndex)) return false; if (m_storage.IsSpanMode() == 1) { TRACE(_T("You cannot extract from the span in creation.\n")); return false; } if (m_iFileOpened) { TRACE(_T("A file already opened.\n")); return false; } m_info.Init(); m_centralDir.OpenFile(uIndex); WORD uMethod = CurrentFile()->m_uMethod; if ((uMethod != 0) &&(uMethod != Z_DEFLATED)) ThrowError(ZIP_BADZIPFILE); if (uMethod == Z_DEFLATED) { m_info.m_stream.opaque = m_bDetectZlibMemoryLeaks ? &m_list : 0; int err = inflateInit2(&m_info.m_stream, -MAX_WBITS); // * windowBits is passed < 0 to tell that there is no zlib header. // * Note that in this case inflate *requires* an extra "dummy" byte // * after the compressed stream in order to complete decompression and // * return Z_STREAM_END. CheckForError(err); } m_info.m_uComprLeft = CurrentFile()->m_uComprSize; m_info.m_uUncomprLeft = CurrentFile()->m_uUncomprSize; m_info.m_uCrc32 = 0; m_info.m_stream.total_out = 0; m_info.m_stream.avail_in = 0; m_iFileOpened = extract; return true; }
void GLES2ShaderContext::CreateProgram() { GLuint currentProgram = 0; { const std::size_t programHash = ComputeProgramHashValue(m_currentVS, m_currentPS); std::map<std::size_t, GLuint>::iterator iter = m_programs.find(programHash); if (iter == m_programs.end()) { std::stringstream ss; ss << "#" << programHash << " - " << m_currentVS->GetShaderName() << " @ " << m_currentPS->GetShaderName(); const str_type::string programName = ss.str(); const GLuint program = CreateProgramFromCurrentShaders(); if (program) { m_programs[programHash] = program; currentProgram = program; m_logger.Log(programName + " successfully created", Platform::FileLogger::INFO); if (!FindLocations(currentProgram)) { m_logger.Log(m_currentVS->GetShaderName() + m_currentPS->GetShaderName() + " does not have necessary attribs", Platform::FileLogger::ERROR); } } else { m_logger.Log(programName + " failed", Platform::FileLogger::ERROR); } } else { currentProgram = iter->second; } if (m_currentProgram != currentProgram) { m_currentProgram = currentProgram; glUseProgram(currentProgram); CheckForError("glUseProgram"); } } }
void CDeflateCompressor::InitCompression(int iLevel, CZipFileHeader* pFile, CZipCryptograph* pCryptograph) { CZipCompressor::InitCompression(iLevel, pFile, pCryptograph); m_stream.avail_in = (zarch_uInt)0; m_stream.avail_out = (zarch_uInt)m_pBuffer.GetSize(); m_stream.next_out = (zarch_Bytef*)(char*)m_pBuffer; m_stream.total_in = 0; m_stream.total_out = 0; if (pFile->m_uMethod == methodDeflate) { SetOpaque(&m_stream.opaque, &m_options); int err = zarch_deflateInit2_(&m_stream, iLevel, Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, ZLIB_VERSION, sizeof(zarch_z_stream)); CheckForError(err); } }
void CDeflateCompressor::Compress(const void *pBuffer, DWORD uSize) { UpdateFileCrc(pBuffer, uSize); if (m_pFile->m_uMethod == methodDeflate) { m_stream.next_in = (zarch_Bytef*)pBuffer; m_stream.avail_in = uSize; while (m_stream.avail_in > 0) { if (m_stream.avail_out == 0) { FlushWriteBuffer(); m_stream.avail_out = m_pBuffer.GetSize(); m_stream.next_out = (zarch_Bytef*)(char*)m_pBuffer; } ZIP_ZLIB_TYPE uTotal = m_stream.total_out; CheckForError(zarch_deflate(&m_stream, Z_NO_FLUSH)); m_uComprLeft += m_stream.total_out - uTotal; } } else if (uSize > 0) { if (m_pCryptograph) { if (m_pBuffer.GetSize() < uSize) { m_pBuffer.Allocate(uSize); } memcpy(m_pBuffer, pBuffer, uSize); WriteBuffer(m_pBuffer, uSize); } else m_pStorage->Write(pBuffer, uSize, false); m_stream.total_in += uSize; m_stream.total_out += uSize; } }
//----------------------------------------------------------------------------- // Variable_BindParameter() // Allocate a variable and bind it to the given statement. //----------------------------------------------------------------------------- static int Variable_BindParameter( udt_Variable *self, // variable to bind udt_Cursor *cursor, // cursor to bind to SQLUSMALLINT position) // position to bind to { SQLSMALLINT inputOutputType; SQLRETURN rc; self->position = position; if (self->input && self->output) inputOutputType = SQL_PARAM_INPUT_OUTPUT; else if (self->output) inputOutputType = SQL_PARAM_OUTPUT; else inputOutputType = SQL_PARAM_INPUT; rc = SQLBindParameter(cursor->handle, position, inputOutputType, self->type->cDataType, self->type->sqlDataType, self->size, self->scale, self->data, self->bufferSize, self->lengthOrIndicator); if (CheckForError(cursor, rc, "Variable_BindParameter()") < 0) return -1; return 0; }
//----------------------------------------------------------------------------- // Variable_NewForResultSet() // Create a new variable for the given position in the result set. The new // variable is immediately bound to the statement as well. //----------------------------------------------------------------------------- static udt_Variable *Variable_NewForResultSet( udt_Cursor *cursor, // cursor in use SQLUSMALLINT position) // position in define list { SQLSMALLINT dataType, length, scale, nullable; udt_VariableType *varType; CEODBC_CHAR name[1]; udt_Variable *var; SQLULEN size; SQLRETURN rc; // retrieve information about the column rc = SQLDescribeCol(cursor->handle, position, name, sizeof(name), &length, &dataType, &size, &scale, &nullable); if (CheckForError(cursor, rc, "Variable_NewForResultSet(): get column info") < 0) return NULL; // determine data type varType = Variable_TypeBySqlDataType(cursor, dataType); if (!varType) return NULL; // some ODBC drivers do not return a long string but instead return string // with a size of zero; provide a workaround if (size == 0) { if (varType == &ceString_VariableType) varType = &ceLongString_VariableType; #if PY_MAJOR_VERSION < 3 else if (varType == &vt_Unicode) varType = &vt_LongUnicode; #endif else if (varType == &vt_Binary) varType = &vt_LongBinary; } // for long columns, set the size appropriately if (varType == &vt_LongUnicode || #if PY_MAJOR_VERSION < 3 varType == &vt_LongString || #endif varType == &vt_LongBinary) { if (cursor->setOutputSize > 0 && (cursor->setOutputSizeColumn == 0 || position == cursor->setOutputSizeColumn)) size = cursor->setOutputSize; else size = varType->defaultSize; } // create a variable of the correct type var = Variable_InternalNew(cursor->fetchArraySize, varType, size, scale); if (!var) return NULL; // bind the column var->position = position; rc = SQLBindCol(cursor->handle, position, var->type->cDataType, var->data, var->bufferSize, var->lengthOrIndicator); if (CheckForError(cursor, rc, "Variable_NewForResultSet(): bind()") < 0) { Py_DECREF(var); return NULL; } return var; }
DWORD CDeflateCompressor::Decompress(void *pBuffer, DWORD uSize) { if (m_bDecompressionDone) return 0; DWORD uRead = 0; if (m_pFile->m_uMethod == methodDeflate) { m_stream.next_out = (zarch_Bytef*)pBuffer; m_stream.avail_out = uSize > m_uUncomprLeft ? (DWORD)m_uUncomprLeft : uSize; // may happen when the file is 0 sized bool bForce = m_stream.avail_out == 0 && m_uComprLeft > 0; while (m_stream.avail_out > 0 || (bForce && m_uComprLeft > 0)) { if (m_stream.avail_in == 0 /* && m_uComprLeft >= 0*/ // Also when there are zero bytes left. It should always be true. ) { DWORD uToRead = FillBuffer(); m_stream.next_in = (zarch_Bytef*)(char*)m_pBuffer; m_stream.avail_in = uToRead; } ZIP_SIZE_TYPE uTotal = m_stream.total_out; zarch_Bytef* pOldBuf = m_stream.next_out; int ret = zarch_inflate(&m_stream, Z_SYNC_FLUSH); // will not exceed DWORD DWORD uToCopy = (DWORD)(m_stream.total_out - uTotal); UpdateCrc(pOldBuf, uToCopy); m_uUncomprLeft -= uToCopy; uRead += uToCopy; if (ret == Z_STREAM_END) { m_bDecompressionDone = true; return uRead; } else CheckForError(ret); } if (!uRead && m_options.m_bCheckLastBlock && uSize != 0) { if (zarch_inflate(&m_stream, Z_SYNC_FLUSH) != Z_STREAM_END) // there were no more bytes to read and there was no ending block, // otherwise the method would return earlier ThrowError(CZipException::badZipFile); } } else { if (m_uComprLeft < uSize) uRead = (DWORD)m_uComprLeft; else uRead = uSize; if (uRead > 0) { m_pStorage->Read(pBuffer, uRead, false); if (m_pCryptograph) m_pCryptograph->Decode((char*)pBuffer, uRead); UpdateCrc(pBuffer, uRead); m_uComprLeft -= uRead; m_uUncomprLeft -= uRead; m_stream.total_out += uRead; } } return uRead; }
bool GLES2ShaderContext::FindLocations(const GLuint program) { m_vertexPosLocations[program] = glGetAttribLocation(program, "vPosition"); m_texCoordLocations[program] = glGetAttribLocation(program, "vTexCoord"); return !CheckForError("GLES2ShaderContext::FindLocations - glGetAttribLocation"); }