mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	- updated func/fift - additional checks in block validator - docs - tunnel prototype in ADNL
		
			
				
	
	
		
			230 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
    This file is part of TON Blockchain Library.
 | 
						|
 | 
						|
    TON Blockchain Library is free software: you can redistribute it and/or modify
 | 
						|
    it under the terms of the GNU Lesser General Public License as published by
 | 
						|
    the Free Software Foundation, either version 2 of the License, or
 | 
						|
    (at your option) any later version.
 | 
						|
 | 
						|
    TON Blockchain Library is distributed in the hope that it will be useful,
 | 
						|
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
    GNU Lesser General Public License for more details.
 | 
						|
 | 
						|
    You should have received a copy of the GNU Lesser General Public License
 | 
						|
    along with TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 | 
						|
    Copyright 2017-2020 Telegram Systems LLP
 | 
						|
*/
 | 
						|
#include "srcread.h"
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
namespace src {
 | 
						|
 | 
						|
/*
 | 
						|
 *
 | 
						|
 *   SOURCE FILE READER
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
std::ostream& operator<<(std::ostream& os, const FileDescr* fdescr) {
 | 
						|
  return os << (fdescr ? (fdescr->is_stdin ? "stdin" : fdescr->filename) : "unknown-location");
 | 
						|
}
 | 
						|
 | 
						|
std::ostream& operator<<(std::ostream& os, const Fatal& fatal) {
 | 
						|
  return os << fatal.get_msg();
 | 
						|
}
 | 
						|
 | 
						|
const char* FileDescr::convert_offset(long offset, long* line_no, long* line_pos, long* line_size) const {
 | 
						|
  long lno = 0, lpos = -1, lsize = 0;
 | 
						|
  const char* lstart = nullptr;
 | 
						|
  if (offset >= 0 && offset < (long)text.size()) {
 | 
						|
    auto it = std::upper_bound(line_offs.begin(), line_offs.end(), offset);
 | 
						|
    lno = it - line_offs.begin();
 | 
						|
    if (lno && it != line_offs.end()) {
 | 
						|
      lsize = it[0] - it[-1];
 | 
						|
      lpos = offset - it[-1];
 | 
						|
      lstart = text.data() + it[-1];
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    lno = (long)line_offs.size();
 | 
						|
  }
 | 
						|
  if (line_no) {
 | 
						|
    *line_no = lno;
 | 
						|
  }
 | 
						|
  if (line_pos) {
 | 
						|
    *line_pos = lpos;
 | 
						|
  }
 | 
						|
  if (line_size) {
 | 
						|
    *line_size = lsize;
 | 
						|
  }
 | 
						|
  return lstart;
 | 
						|
}
 | 
						|
 | 
						|
const char* FileDescr::push_line(std::string new_line) {
 | 
						|
  if (line_offs.empty()) {
 | 
						|
    line_offs.push_back(0);
 | 
						|
  }
 | 
						|
  std::size_t cur_size = text.size();
 | 
						|
  text += new_line;
 | 
						|
  text += '\0';
 | 
						|
  line_offs.push_back((long)text.size());
 | 
						|
  return text.data() + cur_size;
 | 
						|
}
 | 
						|
 | 
						|
void SrcLocation::show(std::ostream& os) const {
 | 
						|
  os << fdescr;
 | 
						|
  long line_no, line_pos;
 | 
						|
  if (fdescr && convert_pos(&line_no, &line_pos)) {
 | 
						|
    os << ':' << line_no;
 | 
						|
    if (line_pos >= 0) {
 | 
						|
      os << ':' << (line_pos + 1);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool SrcLocation::show_context(std::ostream& os) const {
 | 
						|
  long line_no, line_pos, line_size;
 | 
						|
  if (!fdescr || !convert_pos(&line_no, &line_pos, &line_size)) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  bool skip_left = (line_pos > 200), skip_right = (line_pos + 200u < line_size);
 | 
						|
  const char* here = fdescr->text.data() + char_offs;
 | 
						|
  const char* base = here - line_pos;
 | 
						|
  const char* start = skip_left ? here - 100 : base;
 | 
						|
  const char* end = skip_right ? here + 100 : base + line_size;
 | 
						|
  os << "  ";
 | 
						|
  if (skip_left) {
 | 
						|
    os << "... ";
 | 
						|
  }
 | 
						|
  for (const char* ptr = start; ptr < end; ptr++) {
 | 
						|
    os << (char)*ptr;
 | 
						|
  }
 | 
						|
  if (skip_right) {
 | 
						|
    os << " ...";
 | 
						|
  }
 | 
						|
  os << std::endl;
 | 
						|
  os << "  ";
 | 
						|
  if (skip_left) {
 | 
						|
    os << "... ";
 | 
						|
  }
 | 
						|
  for (const char* ptr = start; ptr < here; ptr++) {
 | 
						|
    char c = *ptr;
 | 
						|
    os << (c == 9 || c == 10 ? c : ' ');
 | 
						|
  }
 | 
						|
  os << '^' << std::endl;
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
std::ostream& operator<<(std::ostream& os, const SrcLocation& loc) {
 | 
						|
  loc.show(os);
 | 
						|
  return os;
 | 
						|
}
 | 
						|
 | 
						|
void SrcLocation::show_gen_error(std::ostream& os, std::string message, std::string err_type) const {
 | 
						|
  show(os);
 | 
						|
  if (!err_type.empty()) {
 | 
						|
    os << ": " << err_type;
 | 
						|
  }
 | 
						|
  os << ": " << message << std::endl;
 | 
						|
  show_context(os);
 | 
						|
}
 | 
						|
 | 
						|
std::ostream& operator<<(std::ostream& os, const Error& error) {
 | 
						|
  error.show(os);
 | 
						|
  return os;
 | 
						|
}
 | 
						|
 | 
						|
void ParseError::show(std::ostream& os) const {
 | 
						|
  os << where << ": error: " << message << std::endl;
 | 
						|
  where.show_context(os);
 | 
						|
}
 | 
						|
 | 
						|
SourceReader::SourceReader(std::istream* _is, FileDescr* _fdescr)
 | 
						|
    : ifs(_is), fdescr(_fdescr), loc(_fdescr), eof(false), cur_line_len(0), start(0), cur(0), end(0) {
 | 
						|
  load_line();
 | 
						|
}
 | 
						|
 | 
						|
void SourceReader::set_eof() {
 | 
						|
  if (!eof) {
 | 
						|
    eof = true;
 | 
						|
    start = cur = end = 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
int SourceReader::skip_spc() {
 | 
						|
  if (!cur) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  const char* ptr = cur;
 | 
						|
  int res = 0;
 | 
						|
  while (*ptr == ' ' || *ptr == 9) {
 | 
						|
    ++ptr;
 | 
						|
    ++res;
 | 
						|
  }
 | 
						|
  set_ptr(ptr);
 | 
						|
  return res;
 | 
						|
}
 | 
						|
 | 
						|
bool SourceReader::seek_eof() {
 | 
						|
  while (seek_eoln()) {
 | 
						|
    if (!load_line()) {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
const char* SourceReader::set_ptr(const char* ptr) {
 | 
						|
  if (ptr != cur) {
 | 
						|
    if (ptr < cur || ptr > end) {
 | 
						|
      error("parsing position went outside of line");
 | 
						|
    }
 | 
						|
    loc.char_offs += ptr - cur;
 | 
						|
    cur = ptr;
 | 
						|
  }
 | 
						|
  return ptr;
 | 
						|
}
 | 
						|
 | 
						|
bool SourceReader::load_line() {
 | 
						|
  if (eof) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  loc.set_eof();
 | 
						|
  if (ifs->eof()) {
 | 
						|
    set_eof();
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  std::getline(*ifs, cur_line);
 | 
						|
  if (ifs->fail()) {
 | 
						|
    set_eof();
 | 
						|
    if (!ifs->eof()) {
 | 
						|
      error("cannot read line from source stream");
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  std::size_t len = cur_line.size();
 | 
						|
  if (len > 0xffffff) {
 | 
						|
    set_eof();
 | 
						|
    error("line too long");
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  if (len && cur_line.back() == '\r') {
 | 
						|
    // CP/M line breaks support
 | 
						|
    cur_line.pop_back();
 | 
						|
    --len;
 | 
						|
  }
 | 
						|
  cur_line_len = (int)len;
 | 
						|
  if (fdescr) {
 | 
						|
    cur = start = fdescr->push_line(std::move(cur_line));
 | 
						|
    end = start + len;
 | 
						|
    loc.char_offs = (std::size_t)(cur - fdescr->text.data());
 | 
						|
    cur_line.clear();
 | 
						|
  } else {
 | 
						|
    cur = start = cur_line.c_str();
 | 
						|
    end = start + cur_line_len;
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace src
 |