void IStreams::init() { // simple temporary endian check union { Util::uint32_t l; char c[4]; } u; u.l = 0x01234567; if (u.c[0] != 0x67) { throw std::runtime_error( "Ogawa currently only supports little-endian reading."); } if (mData->streams.empty()) { return; } Alembic::Util::uint64_t firstGroupPos = 0; for (std::size_t i = 0; i < mData->streams.size(); ++i) { char header[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; mData->offsets.push_back(mData->streams[i]->tellg()); mData->streams[i]->read(header, 16); std::string magicStr(header, 5); if (magicStr != "Ogawa") { mData->frozen = false; mData->valid = false; mData->version = 0; return; } bool frozen = (header[5] == char(0xff)); Alembic::Util::uint16_t version = (header[6] << 8) | header[7]; Alembic::Util::uint64_t groupPos = *((Alembic::Util::uint64_t *)(&(header[8]))); if (i == 0) { firstGroupPos = groupPos; mData->frozen = frozen; mData->version = version; } // all the streams have to agree, or we are invalid else if (firstGroupPos != groupPos || mData->frozen != frozen || mData->version != version) { mData->frozen = false; mData->valid = false; mData->version = 0; return; } } mData->valid = true; }
Interpreter::CompilationResult MetaProcessor::readInputFromFile(llvm::StringRef filename, Value* result, bool ignoreOutmostBlock /*=false*/) { { // check that it's not binary: std::ifstream in(filename.str().c_str(), std::ios::in | std::ios::binary); char magic[1024] = {0}; in.read(magic, sizeof(magic)); size_t readMagic = in.gcount(); if (readMagic >= 4) { llvm::StringRef magicStr(magic,in.gcount()); llvm::sys::fs::file_magic fileType = llvm::sys::fs::identify_magic(magicStr); if (fileType != llvm::sys::fs::file_magic::unknown) { llvm::errs() << "Error in cling::MetaProcessor: " "cannot read input from a binary file!\n"; return Interpreter::kFailure; } unsigned printable = 0; for (size_t i = 0; i < readMagic; ++i) if (isprint(magic[i])) ++printable; if (10 * printable < 5 * readMagic) { // 50% printable for ASCII files should be a safe guess. llvm::errs() << "Error in cling::MetaProcessor: " "cannot read input from a (likely) binary file!\n" << printable; return Interpreter::kFailure; } } } std::ifstream in(filename.str().c_str()); in.seekg(0, std::ios::end); size_t size = in.tellg(); std::string content(size, ' '); in.seekg(0); in.read(&content[0], size); if (ignoreOutmostBlock && !content.empty()) { static const char whitespace[] = " \t\r\n"; std::string::size_type posNonWS = content.find_first_not_of(whitespace); // Handle comments before leading { while (content[posNonWS] == '/' && content[posNonWS+1] == '/') { // Remove the comment line posNonWS = content.find_first_of('\n', posNonWS+2)+1; } std::string::size_type replaced = posNonWS; if (posNonWS != std::string::npos) { if (content[posNonWS] == '{') { // hide the curly brace: content[posNonWS] = ' '; // and the matching closing '}' posNonWS = content.find_last_not_of(whitespace); if (posNonWS != std::string::npos) { if (content[posNonWS] == ';' && content[posNonWS-1] == '}') { content[posNonWS--] = ' '; // replace ';' and enter next if } if (content[posNonWS] == '}') { content[posNonWS] = ' '; // replace '}' } else { std::string::size_type posComment = content.find_last_of('}'); if (content[posComment] == '}') { content[posComment] = ' '; // replace '}' } posComment = content.find_first_not_of(whitespace, posComment); if (content[posComment] == '/' && content[posComment+1] == '/') { // More text (comments) are okay after the last '}', but // we can not easily find it to remove it (so we need to upgrade // this code to better handle the case with comments or // preprocessor code before and after the leading { and // trailing }) while (posComment <= posNonWS) { content[posComment++] = ' '; // replace '}' and comment } } else { content[replaced] = '{'; // By putting the '{' back, we keep the code as consistent as // the user wrote it ... but we should still warn that we not // goint to treat this file an unamed macro. llvm::errs() << "Warning in cling::MetaProcessor: can not find the closing '}', " << llvm::sys::path::filename(filename) << " is not handled as an unamed script!\n"; } // did not find '}'' } // remove comments after the trailing '}' } // find '}' } // have '{' } // have non-whitespace } // ignore outmost block std::string strFilename(filename.str()); m_CurrentlyExecutingFile = strFilename; bool topmost = !m_TopExecutingFile.data(); if (topmost) m_TopExecutingFile = m_CurrentlyExecutingFile; Interpreter::CompilationResult ret; // We don't want to value print the results of a unnamed macro. content = "#line 2 \"" + filename.str() + "\" \n" + content; if (process((content + ";").c_str(), ret, result)) { // Input file has to be complete. llvm::errs() << "Error in cling::MetaProcessor: file " << llvm::sys::path::filename(filename) << " is incomplete (missing parenthesis or similar)!\n"; ret = Interpreter::kFailure; } m_CurrentlyExecutingFile = llvm::StringRef(); if (topmost) m_TopExecutingFile = llvm::StringRef(); return ret; }
Interpreter::CompilationResult MetaProcessor::readInputFromFile(llvm::StringRef filename, Value* result, size_t posOpenCurly, bool lineByLine) { // FIXME: This will fail for Unicode BOMs (and seems really weird) { // check that it's not binary: std::ifstream in(filename.str().c_str(), std::ios::in | std::ios::binary); if (in.fail()) return reportIOErr(filename, "open"); char magic[1024] = {0}; in.read(magic, sizeof(magic)); size_t readMagic = in.gcount(); // Binary files < 300 bytes are rare, and below newlines etc make the // heuristic unreliable. if (!in.fail() && readMagic >= 300) { llvm::StringRef magicStr(magic,in.gcount()); llvm::file_magic fileType = llvm::identify_magic(magicStr); if (fileType != llvm::file_magic::unknown) return reportIOErr(filename, "read from binary"); unsigned printable = 0; for (size_t i = 0; i < readMagic; ++i) if (isprint(magic[i])) ++printable; if (10 * printable < 5 * readMagic) { // 50% printable for ASCII files should be a safe guess. return reportIOErr(filename, "won't read from likely binary"); } } } std::ifstream in(filename.str().c_str()); if (in.fail()) return reportIOErr(filename, "open"); in.seekg(0, std::ios::end); if (in.fail()) return reportIOErr(filename, "seek"); size_t size = in.tellg(); if (in.fail()) return reportIOErr(filename, "tell"); in.seekg(0); if (in.fail()) return reportIOErr(filename, "rewind"); std::string content(size, ' '); in.read(&content[0], size); if (in.fail()) return reportIOErr(filename, "read"); static const char whitespace[] = " \t\r\n"; if (content.length() > 2 && content[0] == '#' && content[1] == '!') { // Convert shebang line to comment. That's nice because it doesn't // change the content size, leaving posOpenCurly untouched. content[0] = '/'; content[1] = '/'; } if (posOpenCurly != (size_t)-1 && !content.empty()) { assert(content[posOpenCurly] == '{' && "No curly at claimed position of opening curly!"); // hide the curly brace: content[posOpenCurly] = ' '; // and the matching closing '}' size_t posCloseCurly = content.find_last_not_of(whitespace); if (posCloseCurly != std::string::npos) { if (content[posCloseCurly] == ';' && content[posCloseCurly-1] == '}') { content[posCloseCurly--] = ' '; // replace ';' and enter next if } if (content[posCloseCurly] == '}') { content[posCloseCurly] = ' '; // replace '}' } else { std::string::size_type posBlockClose = content.find_last_of('}'); if (posBlockClose != std::string::npos) { content[posBlockClose] = ' '; // replace '}' } std::string::size_type posComment = content.find_first_not_of(whitespace, posBlockClose); if (posComment != std::string::npos && content[posComment] == '/' && content[posComment+1] == '/') { // More text (comments) are okay after the last '}', but // we can not easily find it to remove it (so we need to upgrade // this code to better handle the case with comments or // preprocessor code before and after the leading { and // trailing }) while (posComment <= posCloseCurly) { content[posComment++] = ' '; // replace '}' and comment } } else { content[posCloseCurly] = '{'; // By putting the '{' back, we keep the code as consistent as // the user wrote it ... but we should still warn that we not // goint to treat this file an unamed macro. cling::errs() << "Warning in cling::MetaProcessor: can not find the closing '}', " << llvm::sys::path::filename(filename) << " is not handled as an unamed script!\n"; } // did not find "//" } // remove comments after the trailing '}' } // find '}' } // ignore outermost block m_CurrentlyExecutingFile = filename; bool topmost = !m_TopExecutingFile.data(); if (topmost) m_TopExecutingFile = m_CurrentlyExecutingFile; content.insert(0, "#line 2 \"" + filename.str() + "\" \n"); // We don't want to value print the results of a unnamed macro. if (content.back() != ';') content.append(";"); Interpreter::CompilationResult ret = Interpreter::kSuccess; if (lineByLine) { int rslt = 0; std::string line; std::stringstream ss(content); while (std::getline(ss, line, '\n')) { rslt = process(line, ret, result); if (ret == Interpreter::kFailure) break; } if (rslt) { cling::errs() << "Error in cling::MetaProcessor: file " << llvm::sys::path::filename(filename) << " is incomplete (missing parenthesis or similar)!\n"; } } else ret = m_Interp.process(content, result); m_CurrentlyExecutingFile = llvm::StringRef(); if (topmost) m_TopExecutingFile = llvm::StringRef(); return ret; }