123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529 |
- #include "code.h"
- #include "core-init.h"
- namespace aFuncore {
- Code::~Code(){
- ByteCode *next_tmp;
- while (code != nullptr) {
- if (code->type != ByteCode::code_block || code->data.block.son == nullptr) {
- if (code->next == nullptr) {
- if (code->father == nullptr)
- next_tmp = nullptr;
- else {
- next_tmp = code->father;
- next_tmp->data.block.son = nullptr;
- }
- } else
- next_tmp = code->next;
- delete code;
- code = next_tmp;
- } else
- code = code->data.block.son;
- }
- delete code;
- }
- #ifdef aFunDEBUG
- /**
- * 显式代码内容
- */
- void Code::display() const{
- if (code->type != ByteCode::code_start) {
- errorLog(aFunCoreLogger, "Code display all did not with `start`");
- return;
- }
- const Code::ByteCode *tmp = code;
- while (tmp != nullptr) {
- tmp->display();
- if (tmp->type == ByteCode::code_block && tmp->data.block.son != nullptr) {
- tmp = tmp->data.block.son;
- continue;
- }
- if (tmp->next == nullptr) {
- do {
- tmp = tmp->father;
- } while (tmp != nullptr && tmp->next == nullptr);
- if (tmp == nullptr)
- break;
- tmp = tmp->next;
- } else
- tmp = tmp->next;
- }
- }
- #endif
- #define Done(write) do{ \
- if(!(write)){ \
- errorLog(aFunCoreLogger, "Write/Read bytecode fail: %s [%p]", #write, f); \
- return false; \
- }} while(0)
- /**
- * 代码写入到文件中 (版本: 1)
- * 注意: 不包括 `start`
- * @param f
- * @param debug 是否记录详细的调试信息
- * @return
- */
- bool Code::write_v1(FILE *f, bool debug) const{
- if (code->type != ByteCode::code_start) {
- errorLog(aFunCoreLogger, "Code write all did not with `start`");
- return false;
- } else
- debugLog(aFunCoreLogger, "Write Bytecode to %p (debug: %d)", f, debug);
- const Code::ByteCode *tmp = code;
- while (tmp != nullptr) {
- Done(tmp->write_v1(f, debug));
- if (tmp->type == ByteCode::code_block && tmp->data.block.son != nullptr) {
- tmp = tmp->data.block.son;
- continue;
- }
- if (tmp->next == nullptr) {
- do {
- tmp = tmp->father;
- Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(3)));
- } while (tmp != nullptr && tmp->next == nullptr);
- if (tmp == nullptr)
- break;
- tmp = tmp->next;
- } else
- tmp = tmp->next;
- }
- Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(0)));
- return true;
- }
- /**
- * 读取文件中的code (版本: 1)
- * @param f
- * @param debug 文件是否包含 debug 信息
- * @return
- */
- bool Code::read_v1(FILE *f, bool debug) {
- if (code->type != ByteCode::code_start) {
- errorLog(aFunCoreLogger, "Code read all did not with `start`");
- return false;
- } else
- debugLog(aFunCoreLogger, "Read Bytecode from %p (debug: %d)", f, debug);
- Code::ByteCode *father_ = nullptr;
- Code::ByteCode *next_ = code;
- const Code::ByteCode *tmp = code;
- while (tmp != nullptr) {
- int8_t type_ = aFuntool::NUL;
- Done(aFuntool::byteReadInt(f, &type_));
- switch (type_) {
- case 0:
- goto RETURN;
- case 3:
- if (next_ == nullptr) {
- errorLog(aFunCoreLogger, "Code without father");
- return false;
- }
- next_ = next_->father;
- break;
- default: {
- Code::ByteCode *ret;
- if (next_ == nullptr && father_ != nullptr)
- ret = father_->read_v1(f, debug, type_, true);
- else if (next_ != nullptr)
- ret = next_->read_v1(f, debug, type_, false);
- else {
- errorLog(aFunCoreLogger, "Code read with unknown error");
- return false;
- }
- if (ret == nullptr) {
- errorLog(aFunCoreLogger, "Code read fail");
- return false;
- } else if (type_ == ByteCode::code_block) {
- next_ = nullptr;
- father_ = ret;
- } else {
- next_ = ret;
- father_ = nullptr;
- }
- break;
- }
- }
- }
- RETURN:
- return true;
- }
- #undef Done
- /**
- * 计算代码的MD5值(版本:1)
- * @return md5
- */
- std::string Code::getMD5_v1() const{
- if (code->type != ByteCode::code_start) {
- errorLog(aFunCoreLogger, "Code get md5 all did not with `start`");
- return "";
- }
- char md5str[aFuntool::MD5_STR_LEN + 1]{};
- char md5_value[aFuntool::MD5_SIZE];
- aFuntool::MD5_CTX *md5 = aFuntool::MD5Init();
- const Code::ByteCode *tmp = code;
- while (tmp != nullptr) {
- std::string code_md5 = tmp->getMD5_v1();
- MD5Update(md5, (unsigned char *) code_md5.c_str(), (unsigned int)code_md5.size());
- if (tmp->type == ByteCode::code_block && tmp->data.block.son != nullptr) {
- tmp = tmp->data.block.son;
- continue;
- }
- if (tmp->next == nullptr) {
- do {
- tmp = tmp->father;
- } while (tmp != nullptr && tmp->next == nullptr);
- if (tmp == nullptr)
- break;
- tmp = tmp->next;
- } else
- tmp = tmp->next;
- }
- MD5Final(md5, (unsigned char *) md5_value);
- for (int i = 0; i < aFuntool::MD5_SIZE; i++)
- snprintf((char *) md5str + i * 2, 2 + 1, "%02x", md5_value[i]);
- return md5str;
- }
- static const std::string ByteCodeHead = "aFunByteCode"; // NOLINT
- static const int MaxByteCodeVersion = 1; // 字节码版本号, 有别于 aFun 版本号
- #define Done(write) do{ \
- if(!(write)){ \
- errorLog(aFunCoreLogger, "Write/Read bytecode file fail: %s [%p]", #write, f); \
- goto RETURN_FALSE; \
- }}while(0)
- /**
- * 生成字节码文件(版本: MaxByteCodeVersion)
- * @param file_path
- * @param debug
- * @return
- */
- bool Code::writeByteCode(const aFuntool::FilePath &file_path, bool debug) const{
- if (code->type != ByteCode::code_start) {
- errorLog(aFunCoreLogger, "ByteCode write all did not with `start`");
- return false;
- }
- FILE *f = aFuntool::fileOpen(file_path, "wb");
- if (f == nullptr) {
- errorLog(aFunCoreLogger, "Write ByteCode file create file fail.");
- return false;
- } else
- debugLog(aFunCoreLogger, "Write Bytecode file %s [%p] (debug: %d)", file_path.c_str(), f, debug);
- Done(aFuntool::byteWriteStr(f, ByteCodeHead));
- Done(aFuntool::byteWriteInt(f, int16_t(MaxByteCodeVersion)));
- Done(aFuntool::byteWriteStr(f, getMD5_v1()));
- Done(aFuntool::byteWriteInt(f, int8_t(debug)));
- Done(write_v1(f, debug));
- aFuntool::fileClose(f);
- debugLog(aFunCoreLogger, "Write Bytecode file success");
- return true;
- RETURN_FALSE:
- aFuntool::fileClose(f);
- debugLog(aFunCoreLogger, "Write Bytecode file fail");
- return false;
- }
- /**
- * 读取字节码文件(版本: 自动识别)
- * @param file_path
- * @return
- */
- bool Code::readByteCode(const aFuntool::FilePath &file_path){
- if (code->type != ByteCode::code_start) {
- errorLog(aFunCoreLogger, "ByteCode read all did not with `start`");
- return false;
- }
- FILE *f = aFuntool::fileOpen(file_path, "rb");
- if (f == nullptr) {
- warningLog(aFunCoreLogger, "Read ByteCode read file fail.");
- return false;
- } else
- debugLog(aFunCoreLogger, "Read Bytecode file %s [%p]", file_path.c_str(), f);
- std::string head;
- Done(aFuntool::byteReadStr(f, head));
- if (head != ByteCodeHead)
- return false;
- int16_t version;
- Done(aFuntool::byteReadInt(f, &version));
- switch (version) { // NOLINT 为拓展方便, 使用switch-case而不是if-else
- case 1: {
- debugLog(aFunCoreLogger, "Read Bytecode file version 1");
- std::string md5;
- int8_t debug;
- Done(aFuntool::byteReadStr(f, md5));
- Done(aFuntool::byteReadInt(f, &debug));
- Done(read_v1(f, debug));
- std::string md5_ = getMD5_v1();
- if (md5_ != md5)
- goto RETURN_FALSE;
- break;
- }
- default:
- errorLog(aFunCoreLogger, "Read Bytecode file bad version");
- goto RETURN_FALSE;
- }
- aFuntool::fileClose(f);
- debugLog(aFunCoreLogger, "Read Bytecode file success");
- return true;
- RETURN_FALSE:
- aFuntool::fileClose(f);
- debugLog(aFunCoreLogger, "Read Bytecode file fail");
- return false;
- }
- #undef Done
- /**
- * 创建 `start` 代码块
- * @param line
- * @param file
- */
- Code::ByteCode::ByteCode(Code &belong_, aFuntool::FileLine line) : belong{belong_} { // NOLINT 不初始化 element, block_type, son
- this->type = code_start;
- this->line = line;
- }
- /**
- * 创建 `element` 代码块
- * @param element
- * @param line
- * @param file
- * @param prefix
- */
- Code::ByteCode::ByteCode(Code &belong_, const std::string &element, aFuntool::FileLine line,
- char prefix) : belong{belong_}{ // NOLINT 不初始化 block_type, son
- this->type = code_element;
- this->prefix = prefix;
- this->line = line;
- if (!aFuntool::isCharUTF8(element)) {
- errorLog(aFunCoreLogger, "Element not utf-8");
- this->data.element = nullptr;
- } else
- this->data.element = aFuntool::strCopy(element.c_str());
- }
- /**
- * 创建 `block` 代码块
- * @param block_type
- * @param son
- * @param line
- * @param file
- * @param prefix
- */
- Code::ByteCode::ByteCode(Code &belong_, BlockType block_type, Code::ByteCode *son, aFuntool::FileLine line,
- char prefix) : belong{belong_} { // NOLINT 不出时候 element
- this->type = code_block;
- this->prefix = prefix;
- this->line = line;
- this->data.block.block_type = block_type;
- this->data.block.son = son;
- for (Code::ByteCode *tmp = son; tmp != nullptr; tmp = tmp->next)
- tmp->father = this;
- }
- Code::ByteCode::~ByteCode(){
- if (type == code_element)
- aFuntool::safeFree(data.element);
- }
- /**
- * 连结代码块
- * @param new_code
- * @return
- */
- Code::ByteCode *Code::ByteCode::connect(Code::ByteCode *new_code){
- Code::ByteCode *tmp = this;
- while (tmp->next != nullptr)
- tmp = tmp->next;
- if (new_code == nullptr)
- return tmp;
- if (new_code->type == code_start) {
- errorLog(aFunCoreLogger, "Code connect with `start`");
- return tmp;
- }
- if (&new_code->belong != &tmp->belong) {
- errorLog(aFunCoreLogger, "Code connect with difference belong");
- return tmp;
- }
- Code::ByteCode *father_ = tmp->father;
- tmp->next = new_code;
- new_code->prev = tmp;
- while (new_code->next != nullptr) {
- new_code = new_code->next;
- new_code->father = father_;
- }
- return new_code;
- }
- #ifdef aFunDEBUG
- /**
- * 显式代码块内容
- */
- void Code::ByteCode::display() const{
- aFuntool::cout << (char)(prefix == aFuntool::NUL ? '-' : prefix) << "[father: " << father << "] type=" << type << " " << this;
- if (type == code_element)
- aFuntool::cout << " element: " << data.element << "\n";
- else if (type == code_block)
- aFuntool::cout << " block: '" << (char)(data.block.block_type) << "' son: " << data.block.son << "\n";
- else
- aFuntool::cout << "\n";
- }
- #endif
- #define Done(write) do{ \
- if(!(write)){ \
- errorLog(aFunCoreLogger, "Write Code::ByteCode fail: %s [%p]", #write, f); \
- return false; \
- }}while(0)
- /**
- * 将code写入到文件中 (版本: 1)
- * @param f
- * @param debug 是否记录 debug 信息
- * @return
- */
- bool Code::ByteCode::write_v1(FILE *f, bool debug) const{
- switch (type) {
- case code_element:
- Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(code_element)));
- Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(prefix)));
- Done(aFuntool::byteWriteStr(f, (data.element)));
- break;
- case code_block:
- if (data.block.son == nullptr)
- Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(4))); // 空 block 标注为 4
- else
- Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(code_block)));
- Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(prefix)));
- Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(data.block.block_type)));
- break;
- default:
- break;
- }
- if (debug)
- Done(aFuntool::byteWriteInt(f, static_cast<int16_t>(line)));
- return true;
- }
- #undef Done
- #define Done(write) do{ \
- if(!(write)){ \
- errorLog(aFunCoreLogger, "Read Code::ByteCode fail: %s [%p]", #write, f); \
- return nullptr; \
- }}while(0)
- /**
- * 读取 code 并拼接到 next 或 son 中 (版本: 1)
- * @param f
- * @param debug 文件是否包含 debug 信息
- * @param read_type 读取类型
- * @param to_son 若位true则拼接到son, 否则拼接到next
- * @return
- */
- Code::ByteCode *Code::ByteCode::read_v1(FILE *f, bool debug, int8_t read_type, bool to_son){
- Code::ByteCode *ret;
- switch (read_type) {
- case code_element: {
- int8_t prefix_ = aFuntool::NUL;
- std::string element_;
- Done(aFuntool::byteReadInt(f, &prefix_));
- Done(aFuntool::byteReadStr(f, element_));
- ret = new Code::ByteCode(belong, element_, 0, char(prefix_));
- break;
- }
- case 4:
- case code_block: {
- int8_t prefix_ = aFuntool::NUL;
- int8_t block_type = aFuntool::NUL;
- Done(aFuntool::byteReadInt(f, &prefix_));
- Done(aFuntool::byteReadInt(f, &block_type));
- ret = new Code::ByteCode(belong, BlockType(block_type), nullptr, 0, char(prefix_));
- break;
- }
- default:
- errorLog(aFunCoreLogger, "Read code with bad type.");
- return nullptr;
- }
- if (debug) {
- int16_t line_ = aFuntool::NUL;
- Done(aFuntool::byteReadInt(f, &line_));
- ret->line = line;
- }
- if (to_son) {
- if (type != code_block || data.block.son != nullptr) {
- errorLog(aFunCoreLogger, "Read son with bad type.");
- delete ret;
- return nullptr;
- }
- ret->father = this;
- data.block.son = ret;
- } else
- connect(ret);
- return ret;
- }
- #undef Done
- /**
- * 计算代码的MD5值(版本:1)
- * @return md5
- */
- std::string Code::ByteCode::getMD5_v1() const{
- char md5str[aFuntool::MD5_STR_LEN + 1]{};
- char md5_value[aFuntool::MD5_SIZE];
- aFuntool::MD5_CTX *md5 = aFuntool::MD5Init();
- char head[] = {static_cast<char>(type), prefix, 'x', 'x', aFuntool::NUL};
- if (prefix == aFuntool::NUL)
- head[1] = '-';
- if (type == code_block) {
- head[2] = data.block.son == nullptr ? 'n' : 's';
- head[3] = (char)data.block.block_type;
- }
- MD5Update(md5, (unsigned char *) head, (unsigned int)strlen((char *) head));
- if (type == code_element)
- MD5Update(md5, (unsigned char *) data.element, (unsigned int)strlen((char *) data.element));
- else if (type == code_block)
- MD5Update(md5, (unsigned char *) "block", 5);
- else
- MD5Update(md5, (unsigned char *) "start", 5);
- MD5Final(md5, (unsigned char *) md5_value);
- for (int i = 0; i < aFuntool::MD5_SIZE; i++)
- snprintf((char *) md5str + i * 2, 2 + 1, "%02x", md5_value[i]);
- return md5str;
- }
- }
|