|
@@ -1,157 +1,42 @@
|
|
|
#include "code.h"
|
|
|
#include "init.h"
|
|
|
-namespace aFuncore {
|
|
|
-
|
|
|
-/**
|
|
|
- * 创建 `start` 代码块
|
|
|
- * @param line
|
|
|
- * @param file
|
|
|
- */
|
|
|
- Code::Code(aFuntool::FileLine line, aFuntool::ConstFilePath file){ // NOLINT 不初始化 element, block_type, son
|
|
|
- this->type = code_start;
|
|
|
- if (file.empty()) {
|
|
|
- errorLog(aFunCoreLogger, "Make `start` code without FilePath");
|
|
|
- this->file = nullptr;
|
|
|
- } else
|
|
|
- this->file = aFuntool::strCopy(file.c_str());
|
|
|
- this->line = line;
|
|
|
- }
|
|
|
-
|
|
|
-/**
|
|
|
- * 创建 `element` 代码块
|
|
|
- * @param element
|
|
|
- * @param line
|
|
|
- * @param file
|
|
|
- * @param prefix
|
|
|
- */
|
|
|
- Code::Code(const std::string &element, aFuntool::FileLine line, aFuntool::ConstFilePath file,
|
|
|
- char prefix){ // NOLINT 不初始化 block_type, son
|
|
|
- this->type = code_element;
|
|
|
- this->prefix = prefix;
|
|
|
- if (file.empty())
|
|
|
- this->file = nullptr;
|
|
|
- else
|
|
|
- this->file = aFuntool::strCopy(file.c_str());
|
|
|
- this->line = line;
|
|
|
-
|
|
|
- if (!aFuntool::isCharUTF8(element)) {
|
|
|
- errorLog(aFunCoreLogger, "Element not utf-8");
|
|
|
- this->element = nullptr;
|
|
|
- } else
|
|
|
- this->element = aFuntool::strCopy(element.c_str());
|
|
|
- }
|
|
|
-
|
|
|
-/**
|
|
|
- * 创建 `block` 代码块
|
|
|
- * @param block_type
|
|
|
- * @param son
|
|
|
- * @param line
|
|
|
- * @param file
|
|
|
- * @param prefix
|
|
|
- */
|
|
|
- Code::Code(BlockType block_type, Code *son, aFuntool::FileLine line, aFuntool::ConstFilePath file, char prefix){ // NOLINT 不出时候 element
|
|
|
- this->type = code_block;
|
|
|
- this->prefix = prefix;
|
|
|
- if (file.empty())
|
|
|
- this->file = nullptr;
|
|
|
- else
|
|
|
- this->file = aFuntool::strCopy(file.c_str());
|
|
|
- this->line = line;
|
|
|
-
|
|
|
- this->block_type = block_type;
|
|
|
- this->son = son;
|
|
|
-
|
|
|
- for (Code *tmp = son; tmp != nullptr; tmp = tmp->next)
|
|
|
- tmp->father = this;
|
|
|
- }
|
|
|
|
|
|
+namespace aFuncore {
|
|
|
Code::~Code(){
|
|
|
- if (type == code_element)
|
|
|
- free(element);
|
|
|
- free(file);
|
|
|
- }
|
|
|
-
|
|
|
-/**
|
|
|
- * 连结代码块
|
|
|
- * @param code
|
|
|
- * @return
|
|
|
- */
|
|
|
- Code *Code::connect(Code *code){
|
|
|
- Code *tmp = this;
|
|
|
- while (tmp->next != nullptr)
|
|
|
- tmp = tmp->next;
|
|
|
-
|
|
|
- if (code->type == code_start) {
|
|
|
- errorLog(aFunCoreLogger, "Code connect with `start`");
|
|
|
- return tmp;
|
|
|
- }
|
|
|
-
|
|
|
- Code *father_ = tmp->father;
|
|
|
- tmp->next = code;
|
|
|
- code->prev = tmp;
|
|
|
- while (code->next != nullptr) {
|
|
|
- code = code->next;
|
|
|
- code->father = father_;
|
|
|
- }
|
|
|
- return code;
|
|
|
- }
|
|
|
-
|
|
|
-/**
|
|
|
- * 删除自己以及其子、兄代码块
|
|
|
- */
|
|
|
- void Code::destruct(Code *code){
|
|
|
- if (code->type != code_start) {
|
|
|
- errorLog(aFunCoreLogger, "Code delete did not with `start`");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- Code *next_tmp;
|
|
|
+ ByteCode *next_tmp;
|
|
|
while (code != nullptr) {
|
|
|
- if (code->type != code_block || code->son == nullptr) {
|
|
|
+ if (code->type != ByteCode::code_block || code->data.son == nullptr) {
|
|
|
if (code->next == nullptr) {
|
|
|
if (code->father == nullptr)
|
|
|
next_tmp = nullptr;
|
|
|
else {
|
|
|
next_tmp = code->father;
|
|
|
- next_tmp->son = nullptr;
|
|
|
+ next_tmp->data.son = nullptr;
|
|
|
}
|
|
|
} else
|
|
|
next_tmp = code->next;
|
|
|
delete code;
|
|
|
code = next_tmp;
|
|
|
} else
|
|
|
- code = code->son;
|
|
|
+ code = code->data.son;
|
|
|
}
|
|
|
delete code;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 显式代码块内容
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * 显式自己以及其子、兄代码块
|
|
|
+ */
|
|
|
void Code::display() const{
|
|
|
- aFuntool::printf_stdout(0, "%c[father: %p] type=%d %p", prefix == aFuntool::NUL ? '-' : prefix, father, type, this);
|
|
|
- if (type == code_element)
|
|
|
- aFuntool::printf_stdout(0, " element: %s\n", element);
|
|
|
- else if (type == code_block)
|
|
|
- aFuntool::printf_stdout(0, " block: '%c' son: %p\n", block_type, son);
|
|
|
- else
|
|
|
- aFuntool::printf_stdout(0, "\n");
|
|
|
- }
|
|
|
-
|
|
|
-/**
|
|
|
- * 显式自己以及其子、兄代码块
|
|
|
- */
|
|
|
- void Code::displayAll() const{
|
|
|
- if (this->type != code_start) {
|
|
|
+ if (code->type != ByteCode::code_start) {
|
|
|
errorLog(aFunCoreLogger, "Code dsplay all did not with `start`");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const Code *tmp = this;
|
|
|
+ const Code::ByteCode *tmp = code;
|
|
|
while (tmp != nullptr) {
|
|
|
tmp->display();
|
|
|
- if (tmp->type == code_block && tmp->son != nullptr) {
|
|
|
- tmp = tmp->son;
|
|
|
+ if (tmp->type == ByteCode::code_block && tmp->data.son != nullptr) {
|
|
|
+ tmp = tmp->data.son;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -168,57 +53,24 @@ namespace aFuncore {
|
|
|
}
|
|
|
|
|
|
#define Done(write) do{if(!(write)){return false;}}while(0)
|
|
|
-
|
|
|
-/**
|
|
|
- * 将code写入到文件中 (版本: 1)
|
|
|
- * @param f
|
|
|
- * @param debug 是否记录 debug 信息
|
|
|
- * @return
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * 将的子、兄code写入到文件中 (版本: 1)
|
|
|
+ * 注意: 不包括自己(`start`)
|
|
|
+ * @param f
|
|
|
+ * @param debug
|
|
|
+ * @return
|
|
|
+ */
|
|
|
bool Code::write_v1(FILE *f, bool debug) const{
|
|
|
- switch (type) {
|
|
|
- case code_element:
|
|
|
- Done(aFuntool::byteWriteInt(f, (int8_t) code_element));
|
|
|
- Done(aFuntool::byteWriteInt(f, (int8_t) prefix));
|
|
|
- Done(aFuntool::byteWriteStr(f, element));
|
|
|
- break;
|
|
|
- case code_block:
|
|
|
- if (son == nullptr)
|
|
|
- Done(aFuntool::byteWriteInt(f, (int8_t) 4)); // 空 block 标注为 4
|
|
|
- else
|
|
|
- Done(aFuntool::byteWriteInt(f, (int8_t) code_block));
|
|
|
- Done(aFuntool::byteWriteInt(f, (int8_t) prefix));
|
|
|
- Done(aFuntool::byteWriteInt(f, (int8_t) block_type));
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
-
|
|
|
- }
|
|
|
- if (debug) {
|
|
|
- Done(aFuntool::byteWriteInt(f, (int16_t) line));
|
|
|
- Done(aFuntool::byteWriteStr(f, file));
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
-/**
|
|
|
- * 将的子、兄code写入到文件中 (版本: 1)
|
|
|
- * 注意: 不包括自己(`start`)
|
|
|
- * @param f
|
|
|
- * @param debug
|
|
|
- * @return
|
|
|
- */
|
|
|
- bool Code::writeAll_v1(FILE *f, bool debug) const{
|
|
|
- if (this->type != code_start) {
|
|
|
+ if (code->type != ByteCode::code_start) {
|
|
|
errorLog(aFunCoreLogger, "Code write all did not with `start`");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- const Code *tmp = this;
|
|
|
+ const Code::ByteCode *tmp = code;
|
|
|
while (tmp != nullptr) {
|
|
|
Done(tmp->write_v1(f, debug));
|
|
|
- if (tmp->type == code_block && tmp->son != nullptr) {
|
|
|
- tmp = tmp->son;
|
|
|
+ if (tmp->type == ByteCode::code_block && tmp->data.son != nullptr) {
|
|
|
+ tmp = tmp->data.son;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -237,21 +89,21 @@ namespace aFuncore {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 读取文件中的code (版本: 1)
|
|
|
- * @param f
|
|
|
- * @param debug 文件是否包含 debug 信息
|
|
|
- * @return
|
|
|
- */
|
|
|
- bool Code::readAll_v1(FILE *f, bool debug){
|
|
|
- if (this->type != code_start) {
|
|
|
+ /**
|
|
|
+ * 读取文件中的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;
|
|
|
}
|
|
|
|
|
|
- Code *father_ = nullptr;
|
|
|
- Code *next_ = this;
|
|
|
- const Code *tmp = this;
|
|
|
+ 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_));
|
|
@@ -266,7 +118,7 @@ namespace aFuncore {
|
|
|
next_ = next_->father;
|
|
|
break;
|
|
|
default: {
|
|
|
- Code *ret;
|
|
|
+ Code::ByteCode *ret = nullptr;
|
|
|
if (next_ == nullptr && father_ != nullptr)
|
|
|
ret = father_->read_v1(f, debug, type_, true);
|
|
|
else if (next_ != nullptr)
|
|
@@ -279,7 +131,7 @@ namespace aFuncore {
|
|
|
if (ret == nullptr) {
|
|
|
errorLog(aFunCoreLogger, "Code read error");
|
|
|
return false;
|
|
|
- } else if (type_ == code_block) {
|
|
|
+ } else if (type_ == ByteCode::code_block) {
|
|
|
next_ = nullptr;
|
|
|
father_ = ret;
|
|
|
} else {
|
|
@@ -294,104 +146,14 @@ RETURN:
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-#undef Done
|
|
|
-#define Done(write) do{if(!(write)){return nullptr;}}while(0)
|
|
|
-
|
|
|
-/**
|
|
|
- * 读取 code 并拼接到 next 或 son 中 (版本: 1)
|
|
|
- * @param f
|
|
|
- * @param debug 文件是否包含 debug 信息
|
|
|
- * @param read_type 读取类型
|
|
|
- * @param to_son 若位true则拼接到son, 否则拼接到next
|
|
|
- * @return
|
|
|
- */
|
|
|
- Code *Code::read_v1(FILE *f, bool debug, int8_t read_type, bool to_son){
|
|
|
- Code *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 = Code::create(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 = Code::create(BlockType(block_type), nullptr, 0, "", char(prefix_));
|
|
|
- break;
|
|
|
- }
|
|
|
- default:
|
|
|
- errorLog(aFunCoreLogger, "Read code with error type.");
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- if (debug) {
|
|
|
- int16_t line_ = aFuntool::NUL;
|
|
|
- char *file_ = nullptr;
|
|
|
- Done(aFuntool::byteReadInt(f, &line_));
|
|
|
- Done(aFuntool::byteReadStr(f, file_));
|
|
|
- ret->line = line;
|
|
|
- if (strlen(file) != 0)
|
|
|
- ret->file = aFuntool::strCopy(file);
|
|
|
- }
|
|
|
-
|
|
|
- if (to_son) {
|
|
|
- if (type != code_block || son != nullptr) {
|
|
|
- errorLog(aFunCoreLogger, "Read son with error type.");
|
|
|
- delete ret;
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
- ret->father = this;
|
|
|
- son = ret;
|
|
|
- } else
|
|
|
- connect(ret);
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
#undef Done
|
|
|
|
|
|
-/**
|
|
|
- * 计算代码的MD5值(版本:1)
|
|
|
- * @return md5
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * 计算代码(子、兄)的MD5值(版本:1)
|
|
|
+ * @return md5
|
|
|
+ */
|
|
|
std::string Code::getMD5_v1() const{
|
|
|
- char md5str[aFuntool::MD5_STR_LEN + 1]{};
|
|
|
- char md5_value[aFuntool::MD5_SIZE];
|
|
|
- aFuntool::MD5_CTX *md5 = aFuntool::MD5Init();
|
|
|
-
|
|
|
- char head[] = {(char) type, prefix, 'x', 'x', aFuntool::NUL};
|
|
|
- if (prefix == aFuntool::NUL)
|
|
|
- head[1] = '-';
|
|
|
- if (type == code_block) {
|
|
|
- head[2] = son == nullptr ? 'n' : 's';
|
|
|
- head[3] = block_type;
|
|
|
- }
|
|
|
-
|
|
|
- MD5Update(md5, (unsigned char *) head, strlen((char *) head));
|
|
|
- if (type == code_element)
|
|
|
- MD5Update(md5, (unsigned char *) element, strlen((char *) 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;
|
|
|
- }
|
|
|
-
|
|
|
-/**
|
|
|
- * 计算代码(子、兄)的MD5值(版本:1)
|
|
|
- * @return md5
|
|
|
- */
|
|
|
- std::string Code::getMD5All_v1() const{
|
|
|
- if (this->type != code_start) {
|
|
|
+ if (code->type != ByteCode::code_start) {
|
|
|
errorLog(aFunCoreLogger, "Code get md5 all did not with `start`");
|
|
|
return "";
|
|
|
}
|
|
@@ -400,13 +162,13 @@ RETURN:
|
|
|
char md5_value[aFuntool::MD5_SIZE];
|
|
|
aFuntool::MD5_CTX *md5 = aFuntool::MD5Init();
|
|
|
|
|
|
- const Code *tmp = this;
|
|
|
+ const Code::ByteCode *tmp = code;
|
|
|
while (tmp != nullptr) {
|
|
|
std::string code_md5 = tmp->getMD5_v1();
|
|
|
MD5Update(md5, (unsigned char *) code_md5.c_str(), code_md5.size());
|
|
|
|
|
|
- if (tmp->type == code_block && tmp->son != nullptr) {
|
|
|
- tmp = tmp->son;
|
|
|
+ if (tmp->type == ByteCode::code_block && tmp->data.son != nullptr) {
|
|
|
+ tmp = tmp->data.son;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -432,14 +194,14 @@ RETURN:
|
|
|
|
|
|
#define Done(write) do{if(!(write)){goto RETURN_FALSE;}}while(0)
|
|
|
|
|
|
-/**
|
|
|
- * 生成字节码文件(版本: MaxByteCodeVersion)
|
|
|
- * @param file_path
|
|
|
- * @param debug
|
|
|
- * @return
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * 生成字节码文件(版本: MaxByteCodeVersion)
|
|
|
+ * @param file_path
|
|
|
+ * @param debug
|
|
|
+ * @return
|
|
|
+ */
|
|
|
bool Code::writeByteCode(aFuntool::ConstFilePath file_path, bool debug) const{
|
|
|
- if (this->type != code_start) {
|
|
|
+ if (code->type != ByteCode::code_start) {
|
|
|
errorLog(aFunCoreLogger, "ByteCode write all did not with `start`");
|
|
|
return false;
|
|
|
}
|
|
@@ -452,9 +214,9 @@ RETURN:
|
|
|
|
|
|
Done(aFuntool::byteWriteStr(f, ByteCodeHead));
|
|
|
Done(aFuntool::byteWriteInt(f, int16_t(MaxByteCodeVersion)));
|
|
|
- Done(aFuntool::byteWriteStr(f, getMD5All_v1()));
|
|
|
+ Done(aFuntool::byteWriteStr(f, getMD5_v1()));
|
|
|
Done(aFuntool::byteWriteInt(f, int8_t(debug)));
|
|
|
- Done(writeAll_v1(f, debug));
|
|
|
+ Done(write_v1(f, debug));
|
|
|
aFuntool::fileClose(f);
|
|
|
return true;
|
|
|
|
|
@@ -463,13 +225,13 @@ RETURN_FALSE:
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 读取字节码文件(版本: 自动识别)
|
|
|
- * @param file_path
|
|
|
- * @return
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * 读取字节码文件(版本: 自动识别)
|
|
|
+ * @param file_path
|
|
|
+ * @return
|
|
|
+ */
|
|
|
bool Code::readByteCode(aFuntool::ConstFilePath file_path){
|
|
|
- if (this->type != code_start) {
|
|
|
+ if (code->type != ByteCode::code_start) {
|
|
|
errorLog(aFunCoreLogger, "ByteCode read all did not with `start`");
|
|
|
return false;
|
|
|
}
|
|
@@ -494,8 +256,8 @@ RETURN_FALSE:
|
|
|
Done(aFuntool::byteReadStr(f, md5));
|
|
|
Done(aFuntool::byteReadInt(f, &debug));
|
|
|
|
|
|
- Done(readAll_v1(f, debug));
|
|
|
- std::string md5_ = getMD5All_v1();
|
|
|
+ Done(read_v1(f, debug));
|
|
|
+ std::string md5_ = getMD5_v1();
|
|
|
if (md5_ != md5)
|
|
|
goto RETURN_FALSE;
|
|
|
return true;
|
|
@@ -512,4 +274,223 @@ 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_type = block_type;
|
|
|
+ this->data.son = son;
|
|
|
+
|
|
|
+ for (Code::ByteCode *tmp = son; tmp != nullptr; tmp = tmp->next)
|
|
|
+ tmp->father = this;
|
|
|
+ }
|
|
|
+
|
|
|
+ Code::ByteCode::~ByteCode(){
|
|
|
+ if (type == code_element)
|
|
|
+ free(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->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;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 显式代码块内容
|
|
|
+ */
|
|
|
+ void Code::ByteCode::display() const{
|
|
|
+ aFuntool::printf_stdout(0, "%c[father: %p] type=%d %p", prefix == aFuntool::NUL ? '-' : prefix, father, type, this);
|
|
|
+ if (type == code_element)
|
|
|
+ aFuntool::printf_stdout(0, " element: %s\n", data.element);
|
|
|
+ else if (type == code_block)
|
|
|
+ aFuntool::printf_stdout(0, " block: '%c' son: %p\n", data.block_type, data.son);
|
|
|
+ else
|
|
|
+ aFuntool::printf_stdout(0, "\n");
|
|
|
+ }
|
|
|
+
|
|
|
+#define Done(write) do{if(!(write)){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, (int8_t) code_element));
|
|
|
+ Done(aFuntool::byteWriteInt(f, (int8_t) prefix));
|
|
|
+ Done(aFuntool::byteWriteStr(f, data.element));
|
|
|
+ break;
|
|
|
+ case code_block:
|
|
|
+ if (data.son == nullptr)
|
|
|
+ Done(aFuntool::byteWriteInt(f, (int8_t) 4)); // 空 block 标注为 4
|
|
|
+ else
|
|
|
+ Done(aFuntool::byteWriteInt(f, (int8_t) code_block));
|
|
|
+ Done(aFuntool::byteWriteInt(f, (int8_t) prefix));
|
|
|
+ Done(aFuntool::byteWriteInt(f, (int8_t) data.block_type));
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+ if (debug)
|
|
|
+ Done(aFuntool::byteWriteInt(f, (int16_t) line));
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+#undef Done
|
|
|
+#define Done(write) do{if(!(write)){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 error 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.son != nullptr) {
|
|
|
+ errorLog(aFunCoreLogger, "Read son with error type.");
|
|
|
+ delete ret;
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+ ret->father = this;
|
|
|
+ data.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[] = {(char) type, prefix, 'x', 'x', aFuntool::NUL};
|
|
|
+ if (prefix == aFuntool::NUL)
|
|
|
+ head[1] = '-';
|
|
|
+ if (type == code_block) {
|
|
|
+ head[2] = data.son == nullptr ? 'n' : 's';
|
|
|
+ head[3] = data.block_type;
|
|
|
+ }
|
|
|
+
|
|
|
+ MD5Update(md5, (unsigned char *) head, strlen((char *) head));
|
|
|
+ if (type == code_element)
|
|
|
+ MD5Update(md5, (unsigned char *) data.element, 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;
|
|
|
+ }
|
|
|
}
|