2
0

code.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. #include "code.h"
  2. #include "core-init.h"
  3. namespace aFuncore {
  4. Code::~Code(){
  5. ByteCode *next_tmp;
  6. while (code != nullptr) {
  7. if (code->type != ByteCode::code_block || code->data.block.son == nullptr) {
  8. if (code->next == nullptr) {
  9. if (code->father == nullptr)
  10. next_tmp = nullptr;
  11. else {
  12. next_tmp = code->father;
  13. next_tmp->data.block.son = nullptr;
  14. }
  15. } else
  16. next_tmp = code->next;
  17. delete code;
  18. code = next_tmp;
  19. } else
  20. code = code->data.block.son;
  21. }
  22. delete code;
  23. }
  24. #ifdef aFunDEBUG
  25. /**
  26. * 显式代码内容
  27. */
  28. void Code::display() const{
  29. if (code->type != ByteCode::code_start) {
  30. errorLog(aFunCoreLogger, "Code display all did not with `start`");
  31. return;
  32. }
  33. const Code::ByteCode *tmp = code;
  34. while (tmp != nullptr) {
  35. tmp->display();
  36. if (tmp->type == ByteCode::code_block && tmp->data.block.son != nullptr) {
  37. tmp = tmp->data.block.son;
  38. continue;
  39. }
  40. if (tmp->next == nullptr) {
  41. do {
  42. tmp = tmp->father;
  43. } while (tmp != nullptr && tmp->next == nullptr);
  44. if (tmp == nullptr)
  45. break;
  46. tmp = tmp->next;
  47. } else
  48. tmp = tmp->next;
  49. }
  50. }
  51. #endif
  52. #define Done(write) do{ \
  53. if(!(write)){ \
  54. errorLog(aFunCoreLogger, "Write/Read bytecode fail: %s [%p]", #write, f); \
  55. return false; \
  56. }} while(0)
  57. /**
  58. * 代码写入到文件中 (版本: 1)
  59. * 注意: 不包括 `start`
  60. * @param f
  61. * @param debug 是否记录详细的调试信息
  62. * @return
  63. */
  64. bool Code::write_v1(FILE *f, bool debug) const{
  65. if (code->type != ByteCode::code_start) {
  66. errorLog(aFunCoreLogger, "Code write all did not with `start`");
  67. return false;
  68. } else
  69. debugLog(aFunCoreLogger, "Write Bytecode to %p (debug: %d)", f, debug);
  70. const Code::ByteCode *tmp = code;
  71. while (tmp != nullptr) {
  72. Done(tmp->write_v1(f, debug));
  73. if (tmp->type == ByteCode::code_block && tmp->data.block.son != nullptr) {
  74. tmp = tmp->data.block.son;
  75. continue;
  76. }
  77. if (tmp->next == nullptr) {
  78. do {
  79. tmp = tmp->father;
  80. Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(3)));
  81. } while (tmp != nullptr && tmp->next == nullptr);
  82. if (tmp == nullptr)
  83. break;
  84. tmp = tmp->next;
  85. } else
  86. tmp = tmp->next;
  87. }
  88. Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(0)));
  89. return true;
  90. }
  91. /**
  92. * 读取文件中的code (版本: 1)
  93. * @param f
  94. * @param debug 文件是否包含 debug 信息
  95. * @return
  96. */
  97. bool Code::read_v1(FILE *f, bool debug) {
  98. if (code->type != ByteCode::code_start) {
  99. errorLog(aFunCoreLogger, "Code read all did not with `start`");
  100. return false;
  101. } else
  102. debugLog(aFunCoreLogger, "Read Bytecode from %p (debug: %d)", f, debug);
  103. Code::ByteCode *father_ = nullptr;
  104. Code::ByteCode *next_ = code;
  105. const Code::ByteCode *tmp = code;
  106. while (tmp != nullptr) {
  107. int8_t type_ = aFuntool::NUL;
  108. Done(aFuntool::byteReadInt(f, &type_));
  109. switch (type_) {
  110. case 0:
  111. goto RETURN;
  112. case 3:
  113. if (next_ == nullptr) {
  114. errorLog(aFunCoreLogger, "Code without father");
  115. return false;
  116. }
  117. next_ = next_->father;
  118. break;
  119. default: {
  120. Code::ByteCode *ret;
  121. if (next_ == nullptr && father_ != nullptr)
  122. ret = father_->read_v1(f, debug, type_, true);
  123. else if (next_ != nullptr)
  124. ret = next_->read_v1(f, debug, type_, false);
  125. else {
  126. errorLog(aFunCoreLogger, "Code read with unknown error");
  127. return false;
  128. }
  129. if (ret == nullptr) {
  130. errorLog(aFunCoreLogger, "Code read fail");
  131. return false;
  132. } else if (type_ == ByteCode::code_block) {
  133. next_ = nullptr;
  134. father_ = ret;
  135. } else {
  136. next_ = ret;
  137. father_ = nullptr;
  138. }
  139. break;
  140. }
  141. }
  142. }
  143. RETURN:
  144. return true;
  145. }
  146. #undef Done
  147. /**
  148. * 计算代码的MD5值(版本:1)
  149. * @return md5
  150. */
  151. std::string Code::getMD5_v1() const{
  152. if (code->type != ByteCode::code_start) {
  153. errorLog(aFunCoreLogger, "Code get md5 all did not with `start`");
  154. return "";
  155. }
  156. char md5str[aFuntool::MD5_STR_LEN + 1]{};
  157. char md5_value[aFuntool::MD5_SIZE];
  158. aFuntool::MD5_CTX *md5 = aFuntool::MD5Init();
  159. const Code::ByteCode *tmp = code;
  160. while (tmp != nullptr) {
  161. std::string code_md5 = tmp->getMD5_v1();
  162. MD5Update(md5, (unsigned char *) code_md5.c_str(), (unsigned int)code_md5.size());
  163. if (tmp->type == ByteCode::code_block && tmp->data.block.son != nullptr) {
  164. tmp = tmp->data.block.son;
  165. continue;
  166. }
  167. if (tmp->next == nullptr) {
  168. do {
  169. tmp = tmp->father;
  170. } while (tmp != nullptr && tmp->next == nullptr);
  171. if (tmp == nullptr)
  172. break;
  173. tmp = tmp->next;
  174. } else
  175. tmp = tmp->next;
  176. }
  177. MD5Final(md5, (unsigned char *) md5_value);
  178. for (int i = 0; i < aFuntool::MD5_SIZE; i++)
  179. snprintf((char *) md5str + i * 2, 2 + 1, "%02x", md5_value[i]);
  180. return md5str;
  181. }
  182. static const std::string ByteCodeHead = "aFunByteCode"; // NOLINT
  183. static const int MaxByteCodeVersion = 1; // 字节码版本号, 有别于 aFun 版本号
  184. #define Done(write) do{ \
  185. if(!(write)){ \
  186. errorLog(aFunCoreLogger, "Write/Read bytecode file fail: %s [%p]", #write, f); \
  187. goto RETURN_FALSE; \
  188. }}while(0)
  189. /**
  190. * 生成字节码文件(版本: MaxByteCodeVersion)
  191. * @param file_path
  192. * @param debug
  193. * @return
  194. */
  195. bool Code::writeByteCode(const aFuntool::FilePath &file_path, bool debug) const{
  196. if (code->type != ByteCode::code_start) {
  197. errorLog(aFunCoreLogger, "ByteCode write all did not with `start`");
  198. return false;
  199. }
  200. FILE *f = aFuntool::fileOpen(file_path, "wb");
  201. if (f == nullptr) {
  202. errorLog(aFunCoreLogger, "Write ByteCode file create file fail.");
  203. return false;
  204. } else
  205. debugLog(aFunCoreLogger, "Write Bytecode file %s [%p] (debug: %d)", file_path.c_str(), f, debug);
  206. Done(aFuntool::byteWriteStr(f, ByteCodeHead));
  207. Done(aFuntool::byteWriteInt(f, int16_t(MaxByteCodeVersion)));
  208. Done(aFuntool::byteWriteStr(f, getMD5_v1()));
  209. Done(aFuntool::byteWriteInt(f, int8_t(debug)));
  210. Done(write_v1(f, debug));
  211. aFuntool::fileClose(f);
  212. debugLog(aFunCoreLogger, "Write Bytecode file success");
  213. return true;
  214. RETURN_FALSE:
  215. aFuntool::fileClose(f);
  216. debugLog(aFunCoreLogger, "Write Bytecode file fail");
  217. return false;
  218. }
  219. /**
  220. * 读取字节码文件(版本: 自动识别)
  221. * @param file_path
  222. * @return
  223. */
  224. bool Code::readByteCode(const aFuntool::FilePath &file_path){
  225. if (code->type != ByteCode::code_start) {
  226. errorLog(aFunCoreLogger, "ByteCode read all did not with `start`");
  227. return false;
  228. }
  229. FILE *f = aFuntool::fileOpen(file_path, "rb");
  230. if (f == nullptr) {
  231. warningLog(aFunCoreLogger, "Read ByteCode read file fail.");
  232. return false;
  233. } else
  234. debugLog(aFunCoreLogger, "Read Bytecode file %s [%p]", file_path.c_str(), f);
  235. std::string head;
  236. Done(aFuntool::byteReadStr(f, head));
  237. if (head != ByteCodeHead)
  238. return false;
  239. int16_t version;
  240. Done(aFuntool::byteReadInt(f, &version));
  241. switch (version) { // NOLINT 为拓展方便, 使用switch-case而不是if-else
  242. case 1: {
  243. debugLog(aFunCoreLogger, "Read Bytecode file version 1");
  244. std::string md5;
  245. int8_t debug;
  246. Done(aFuntool::byteReadStr(f, md5));
  247. Done(aFuntool::byteReadInt(f, &debug));
  248. Done(read_v1(f, debug));
  249. std::string md5_ = getMD5_v1();
  250. if (md5_ != md5)
  251. goto RETURN_FALSE;
  252. break;
  253. }
  254. default:
  255. errorLog(aFunCoreLogger, "Read Bytecode file bad version");
  256. goto RETURN_FALSE;
  257. }
  258. aFuntool::fileClose(f);
  259. debugLog(aFunCoreLogger, "Read Bytecode file success");
  260. return true;
  261. RETURN_FALSE:
  262. aFuntool::fileClose(f);
  263. debugLog(aFunCoreLogger, "Read Bytecode file fail");
  264. return false;
  265. }
  266. #undef Done
  267. /**
  268. * 创建 `start` 代码块
  269. * @param line
  270. * @param file
  271. */
  272. Code::ByteCode::ByteCode(Code &belong_, aFuntool::FileLine line) : belong{belong_} { // NOLINT 不初始化 element, block_type, son
  273. this->type = code_start;
  274. this->line = line;
  275. }
  276. /**
  277. * 创建 `element` 代码块
  278. * @param element
  279. * @param line
  280. * @param file
  281. * @param prefix
  282. */
  283. Code::ByteCode::ByteCode(Code &belong_, const std::string &element, aFuntool::FileLine line,
  284. char prefix) : belong{belong_}{ // NOLINT 不初始化 block_type, son
  285. this->type = code_element;
  286. this->prefix = prefix;
  287. this->line = line;
  288. if (!aFuntool::isCharUTF8(element)) {
  289. errorLog(aFunCoreLogger, "Element not utf-8");
  290. this->data.element = nullptr;
  291. } else
  292. this->data.element = aFuntool::strCopy(element.c_str());
  293. }
  294. /**
  295. * 创建 `block` 代码块
  296. * @param block_type
  297. * @param son
  298. * @param line
  299. * @param file
  300. * @param prefix
  301. */
  302. Code::ByteCode::ByteCode(Code &belong_, BlockType block_type, Code::ByteCode *son, aFuntool::FileLine line,
  303. char prefix) : belong{belong_} { // NOLINT 不出时候 element
  304. this->type = code_block;
  305. this->prefix = prefix;
  306. this->line = line;
  307. this->data.block.block_type = block_type;
  308. this->data.block.son = son;
  309. for (Code::ByteCode *tmp = son; tmp != nullptr; tmp = tmp->next)
  310. tmp->father = this;
  311. }
  312. Code::ByteCode::~ByteCode(){
  313. if (type == code_element)
  314. aFuntool::safeFree(data.element);
  315. }
  316. /**
  317. * 连结代码块
  318. * @param new_code
  319. * @return
  320. */
  321. Code::ByteCode *Code::ByteCode::connect(Code::ByteCode *new_code){
  322. Code::ByteCode *tmp = this;
  323. while (tmp->next != nullptr)
  324. tmp = tmp->next;
  325. if (new_code == nullptr)
  326. return tmp;
  327. if (new_code->type == code_start) {
  328. errorLog(aFunCoreLogger, "Code connect with `start`");
  329. return tmp;
  330. }
  331. if (&new_code->belong != &tmp->belong) {
  332. errorLog(aFunCoreLogger, "Code connect with difference belong");
  333. return tmp;
  334. }
  335. Code::ByteCode *father_ = tmp->father;
  336. tmp->next = new_code;
  337. new_code->prev = tmp;
  338. while (new_code->next != nullptr) {
  339. new_code = new_code->next;
  340. new_code->father = father_;
  341. }
  342. return new_code;
  343. }
  344. #ifdef aFunDEBUG
  345. /**
  346. * 显式代码块内容
  347. */
  348. void Code::ByteCode::display() const{
  349. aFuntool::cout << (char)(prefix == aFuntool::NUL ? '-' : prefix) << "[father: " << father << "] type=" << type << " " << this;
  350. if (type == code_element)
  351. aFuntool::cout << " element: " << data.element << "\n";
  352. else if (type == code_block)
  353. aFuntool::cout << " block: '" << (char)(data.block.block_type) << "' son: " << data.block.son << "\n";
  354. else
  355. aFuntool::cout << "\n";
  356. }
  357. #endif
  358. #define Done(write) do{ \
  359. if(!(write)){ \
  360. errorLog(aFunCoreLogger, "Write Code::ByteCode fail: %s [%p]", #write, f); \
  361. return false; \
  362. }}while(0)
  363. /**
  364. * 将code写入到文件中 (版本: 1)
  365. * @param f
  366. * @param debug 是否记录 debug 信息
  367. * @return
  368. */
  369. bool Code::ByteCode::write_v1(FILE *f, bool debug) const{
  370. switch (type) {
  371. case code_element:
  372. Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(code_element)));
  373. Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(prefix)));
  374. Done(aFuntool::byteWriteStr(f, (data.element)));
  375. break;
  376. case code_block:
  377. if (data.block.son == nullptr)
  378. Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(4))); // 空 block 标注为 4
  379. else
  380. Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(code_block)));
  381. Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(prefix)));
  382. Done(aFuntool::byteWriteInt(f, static_cast<int8_t>(data.block.block_type)));
  383. break;
  384. default:
  385. break;
  386. }
  387. if (debug)
  388. Done(aFuntool::byteWriteInt(f, static_cast<int16_t>(line)));
  389. return true;
  390. }
  391. #undef Done
  392. #define Done(write) do{ \
  393. if(!(write)){ \
  394. errorLog(aFunCoreLogger, "Read Code::ByteCode fail: %s [%p]", #write, f); \
  395. return nullptr; \
  396. }}while(0)
  397. /**
  398. * 读取 code 并拼接到 next 或 son 中 (版本: 1)
  399. * @param f
  400. * @param debug 文件是否包含 debug 信息
  401. * @param read_type 读取类型
  402. * @param to_son 若位true则拼接到son, 否则拼接到next
  403. * @return
  404. */
  405. Code::ByteCode *Code::ByteCode::read_v1(FILE *f, bool debug, int8_t read_type, bool to_son){
  406. Code::ByteCode *ret;
  407. switch (read_type) {
  408. case code_element: {
  409. int8_t prefix_ = aFuntool::NUL;
  410. std::string element_;
  411. Done(aFuntool::byteReadInt(f, &prefix_));
  412. Done(aFuntool::byteReadStr(f, element_));
  413. ret = new Code::ByteCode(belong, element_, 0, char(prefix_));
  414. break;
  415. }
  416. case 4:
  417. case code_block: {
  418. int8_t prefix_ = aFuntool::NUL;
  419. int8_t block_type = aFuntool::NUL;
  420. Done(aFuntool::byteReadInt(f, &prefix_));
  421. Done(aFuntool::byteReadInt(f, &block_type));
  422. ret = new Code::ByteCode(belong, BlockType(block_type), nullptr, 0, char(prefix_));
  423. break;
  424. }
  425. default:
  426. errorLog(aFunCoreLogger, "Read code with bad type.");
  427. return nullptr;
  428. }
  429. if (debug) {
  430. int16_t line_ = aFuntool::NUL;
  431. Done(aFuntool::byteReadInt(f, &line_));
  432. ret->line = line;
  433. }
  434. if (to_son) {
  435. if (type != code_block || data.block.son != nullptr) {
  436. errorLog(aFunCoreLogger, "Read son with bad type.");
  437. delete ret;
  438. return nullptr;
  439. }
  440. ret->father = this;
  441. data.block.son = ret;
  442. } else
  443. connect(ret);
  444. return ret;
  445. }
  446. #undef Done
  447. /**
  448. * 计算代码的MD5值(版本:1)
  449. * @return md5
  450. */
  451. std::string Code::ByteCode::getMD5_v1() const{
  452. char md5str[aFuntool::MD5_STR_LEN + 1]{};
  453. char md5_value[aFuntool::MD5_SIZE];
  454. aFuntool::MD5_CTX *md5 = aFuntool::MD5Init();
  455. char head[] = {static_cast<char>(type), prefix, 'x', 'x', aFuntool::NUL};
  456. if (prefix == aFuntool::NUL)
  457. head[1] = '-';
  458. if (type == code_block) {
  459. head[2] = data.block.son == nullptr ? 'n' : 's';
  460. head[3] = (char)data.block.block_type;
  461. }
  462. MD5Update(md5, (unsigned char *) head, (unsigned int)strlen((char *) head));
  463. if (type == code_element)
  464. MD5Update(md5, (unsigned char *) data.element, (unsigned int)strlen((char *) data.element));
  465. else if (type == code_block)
  466. MD5Update(md5, (unsigned char *) "block", 5);
  467. else
  468. MD5Update(md5, (unsigned char *) "start", 5);
  469. MD5Final(md5, (unsigned char *) md5_value);
  470. for (int i = 0; i < aFuntool::MD5_SIZE; i++)
  471. snprintf((char *) md5str + i * 2, 2 + 1, "%02x", md5_value[i]);
  472. return md5str;
  473. }
  474. }