code.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. /*
  2. * 文件名: code.c
  3. * 目标: 管理Code结构体的函数
  4. */
  5. #include <cstdio>
  6. #include <cctype>
  7. #include "aFunCore.hpp"
  8. #include "tool.hpp"
  9. #include "__code.hpp"
  10. /* Code 创建函数 */
  11. static af_Code *makeCode(char prefix, FileLine line, ConstFilePath path);
  12. static af_Code *freeCode(af_Code *bt);
  13. /* Code 相关操作 */
  14. static int countElement(af_Code *element, CodeUInt *elements, af_Code **next);
  15. /* Code IO函数 */
  16. static bool readCode(af_Code **bt, af_Code *prev, FILE *file);
  17. static bool writeCode(af_Code *bt, FILE *file);
  18. /* Code 转换STR函数 */
  19. struct af_BlockEnd {
  20. char ch;
  21. struct af_BlockEnd *next;
  22. };
  23. static bool checkElementData(char *data);
  24. static char *codeToStr_(af_Code *code, LayerInt *layer, struct af_BlockEnd **bn);
  25. static char *codeEndToStr(CodeUInt code_end, LayerInt *layer, struct af_BlockEnd **bn);
  26. static af_Code *makeCode(char prefix, FileLine line, ConstFilePath path) {
  27. auto bt = calloc(1, af_Code);
  28. bt->line = line;
  29. bt->prefix = prefix;
  30. if (path != nullptr)
  31. bt->path = strCopy(path);
  32. return bt;
  33. }
  34. af_Code *makeElementCode(const char *var, char prefix, FileLine line, ConstFilePath path) {
  35. if (prefix != NUL && strchr(E_PREFIX, prefix) == nullptr)
  36. prefix = NUL;
  37. if (!isCharUTF8(var))
  38. return nullptr;
  39. af_Code *bt = makeCode(prefix, line, path);
  40. bt->type = code_element;
  41. bt->element.data = strCopy(var);
  42. return bt;
  43. }
  44. /* 判断该code是否令layer需要加1 */
  45. /* 即判定是否有子元素 */
  46. #define LAYER_ADD1(code) ((code)->type == code_block && !(code)->block.is_empty)
  47. /*
  48. * 函数名: countElement
  49. * 目标: 统计元素个数(不包括元素的子元素
  50. * 返回1 表示没有跳出过多层级
  51. * 返回2 表示跳出了过多层级
  52. * 返回0 表示错误
  53. */
  54. static int countElement(af_Code *element, CodeUInt *elements, af_Code **next) {
  55. CodeUInt layer = 0; // layer 是相对于当前element的层级数, 可能为负数
  56. af_Code *tmp = nullptr;
  57. if (next == nullptr)
  58. next = &tmp;
  59. for (*elements = 0; element != nullptr; *next = element, element = element->next) {
  60. if (layer == 0)
  61. (*elements)++;
  62. if (LAYER_ADD1(element))
  63. layer++;
  64. if (layer - element->code_end < 0)
  65. return 2;
  66. else
  67. layer = layer - element->code_end;
  68. }
  69. if (layer == 0)
  70. return 1;
  71. else // 大于0, 出现错误
  72. return 0;
  73. }
  74. af_Code *makeBlockCode(enum af_BlockType type, af_Code *element, char prefix, FileLine line, ConstFilePath path, af_Code **next) {
  75. af_Code *tmp = nullptr; // 保存最后一个code的地址
  76. CodeUInt elements = 0;
  77. if (next == nullptr)
  78. next = &tmp;
  79. if (prefix != NUL && strchr(B_PREFIX, prefix) == nullptr)
  80. prefix = NUL;
  81. if (countElement(element, &elements, next) != 1)
  82. return nullptr;
  83. af_Code *bt = makeCode(prefix, line, path);
  84. bt->type = code_block;
  85. bt->block.type = type;
  86. bt->next = element;
  87. if (elements == 0)
  88. bt->block.is_empty = true;
  89. else
  90. (*next)->code_end++; // 若 elements 不为 0, 则next指向最后一个元素
  91. return bt;
  92. }
  93. af_Code *pushCode(af_Code **base, af_Code *next) {
  94. af_Code *prev = nullptr;
  95. while ((*base) != nullptr) {
  96. prev = *base;
  97. base = &(prev->next);
  98. }
  99. next->prev = prev;
  100. *base = next;
  101. while (next != nullptr && next->next != nullptr)
  102. next = next->next;
  103. return next;
  104. }
  105. af_Code *copyAllCode(af_Code *base, ConstFilePath path) {
  106. af_Code *dest = nullptr;
  107. af_Code **pdest = &dest;
  108. af_Code *prev = nullptr;
  109. for(NULL; base != nullptr; base = base->next, prev = *pdest, pdest = &(prev->next)) {
  110. *pdest = makeCode(base->prefix, base->line, base->path);
  111. (*pdest)->type = base->type;
  112. (*pdest)->code_end = base->code_end;
  113. (*pdest)->prev = prev;
  114. switch (base->type) {
  115. case code_element:
  116. (*pdest)->element.data = strCopy(base->element.data);
  117. break;
  118. case code_block:
  119. (*pdest)->block.is_empty = base->block.is_empty;
  120. (*pdest)->block.type = base->block.type;
  121. break;
  122. default:
  123. break;
  124. }
  125. }
  126. if (dest != nullptr && path != nullptr) {
  127. free(dest->path);
  128. dest->path = strCopy(path);
  129. }
  130. return dest;
  131. }
  132. /*
  133. * 函数名: copyCode
  134. * 目标: 拷贝 code, 并为末尾的code设置合适的code_end
  135. */
  136. af_Code *copyCode(af_Code *base){
  137. af_Code *dest = nullptr;
  138. af_Code **pdest = &dest;
  139. af_Code *prev = nullptr;
  140. CodeUInt layer = 0;
  141. for(NULL; base != nullptr; base = base->next, prev = *pdest, pdest = &(prev->next)) {
  142. *pdest = makeCode(base->prefix, base->line, base->path);
  143. (*pdest)->type = base->type;
  144. (*pdest)->prev = prev;
  145. switch (base->type) {
  146. case code_element:
  147. (*pdest)->element.data = strCopy(base->element.data);
  148. break;
  149. case code_block:
  150. (*pdest)->block.is_empty = base->block.is_empty;
  151. (*pdest)->block.type = base->block.type;
  152. break;
  153. default:
  154. break;
  155. }
  156. if (LAYER_ADD1(base))
  157. layer++;
  158. if ((layer - base->code_end) < 0) { // base跳出layer, pdest不能按照base的code_end来, pdest只能刚好跳出layer
  159. (*pdest)->code_end = layer;
  160. break;
  161. } else { // 仍没跳出 layer
  162. (*pdest)->code_end = base->code_end;
  163. layer -= base->code_end;
  164. }
  165. }
  166. return dest;
  167. }
  168. static af_Code *freeCode(af_Code *bt) {
  169. af_Code *next = bt->next;
  170. free(bt->path);
  171. switch (bt->type) {
  172. case code_element:
  173. free(bt->element.data);
  174. break;
  175. default:
  176. break;
  177. }
  178. free(bt);
  179. return next;
  180. }
  181. void freeAllCode(af_Code *bt) {
  182. while (bt != nullptr)
  183. bt = freeCode(bt);
  184. }
  185. af_Code *getCodeNext(af_Code *bt) {
  186. if (!LAYER_ADD1(bt))
  187. return bt->code_end == 0 ? bt->next : nullptr;
  188. CodeUInt layer = 1;
  189. bt = bt->next; // 跳过第一个code_block
  190. while (bt != nullptr) {
  191. if (LAYER_ADD1(bt))
  192. layer++;
  193. if (layer - bt->code_end == 0) // layer为0表示迭代到该block的最后一个元素, 则该元素的下一个元素为该block的Next
  194. return bt->next;
  195. else if (layer - bt->code_end < 0) // 当layer小于0时, 认为已经无next, 即连续跳出了多层
  196. return nullptr;
  197. layer = layer - bt->code_end;
  198. bt = bt->next;
  199. }
  200. return nullptr;
  201. }
  202. af_Code *getCodeElement(af_Code *bt) {
  203. if (!LAYER_ADD1(bt))
  204. return nullptr;
  205. return bt->next;
  206. }
  207. #define Done(write) do{if(!(write)){return false;}}while(0)
  208. static bool writeCode(af_Code *bt, FILE *file) {
  209. Done(byteWriteUint_8(file, bt->type));
  210. Done(byteWriteUint_8(file, bt->prefix));
  211. Done(byteWriteUint_32(file, bt->line));
  212. Done(byteWriteUint_32(file, bt->code_end));
  213. switch (bt->type) {
  214. case code_element:
  215. Done(byteWriteStr(file, bt->element.data));
  216. break;
  217. case code_block:
  218. Done(byteWriteUint_8(file, bt->block.type));
  219. Done(byteWriteUint_8(file, bt->block.is_empty));
  220. break;
  221. default:
  222. break;
  223. }
  224. return true;
  225. }
  226. /*
  227. * 函数名: writeAllCode
  228. * 目标: 将Code写入字节码文件中
  229. * 备注: 写入字节码时不做语义检查, 在读取时最语义检查即可
  230. */
  231. bool writeAllCode(af_Code *bt, FILE *file) {
  232. if (bt == nullptr || bt->path == nullptr)
  233. return false;
  234. if (!codeSemanticCheck(bt))
  235. goto RETURN_FALSE;
  236. for(NULL; bt != nullptr; bt = bt->next) {
  237. if (!writeCode(bt, file))
  238. goto RETURN_FALSE;
  239. if (CLEAR_FERROR(stdin))
  240. goto RETURN_FALSE;
  241. Done(byteWriteUint_8(file, (bt->next == nullptr))); // 记录是否为最后一位
  242. }
  243. return true;
  244. RETURN_FALSE:
  245. return false;
  246. }
  247. static bool readCode(af_Code **bt, af_Code *prev, FILE *file) {
  248. uint8_t type;
  249. uint8_t prefix;
  250. uint32_t line;
  251. uint32_t code_end;
  252. Done(byteReadUint_8(file, &type));
  253. Done(byteReadUint_8(file, &prefix));
  254. Done(byteReadUint_32(file,&line));
  255. Done(byteReadUint_32(file, &code_end));
  256. *bt = makeCode((char)prefix, line, nullptr);
  257. (*bt)->type = (enum af_CodeType)type;
  258. (*bt)->code_end = (CodeUInt)code_end;
  259. (*bt)->prev = prev;
  260. switch (type) {
  261. case code_element:
  262. Done(byteReadStr(file, &((*bt)->element.data)));
  263. break;
  264. case code_block: {
  265. uint8_t block_type;
  266. uint8_t is_empty;
  267. Done(byteReadUint_8(file, &block_type));
  268. Done(byteReadUint_8(file,&is_empty));
  269. (*bt)->block.type = (enum af_BlockType)block_type;
  270. (*bt)->block.is_empty = (CodeUInt)is_empty;
  271. break;
  272. }
  273. default:
  274. break;
  275. }
  276. return true;
  277. }
  278. bool readAllCode(af_Code **bt, ConstFilePath path, FILE *file) {
  279. af_Code **base = bt;
  280. af_Code *prev = nullptr;
  281. *bt = nullptr;
  282. for(NULL; true;prev = *bt, bt = &(prev->next)) {
  283. if(!readCode(bt, prev, file))
  284. goto RETURN_FALSE;
  285. if (CLEAR_FERROR(stdin))
  286. goto RETURN_FALSE;
  287. uint8_t last;
  288. Done(byteReadUint_8(file, &last));
  289. if (last)
  290. break;
  291. }
  292. if (*base != nullptr && path != nullptr)
  293. (*base)->path = strCopy(path);
  294. if (!codeSemanticCheck(*base))
  295. goto RETURN_FALSE;
  296. return true;
  297. RETURN_FALSE:
  298. freeAllCode(*bt);
  299. *bt = nullptr;
  300. return false;
  301. }
  302. /*
  303. * 函数名: checkElementData
  304. * 目标: 检查element中data字符串是否有空白符
  305. */
  306. static bool checkElementData(char *data) {
  307. for (char *ch = data; *ch != NUL; ch++) {
  308. if (isspace(*ch) || *ch == '\n')
  309. return true;
  310. }
  311. return false;
  312. }
  313. /*
  314. * 函数名: codeEndToStr
  315. * 目标: 转换element或开括号为字符串
  316. * 若遇到开括号则设定bn, 并且设定layer
  317. *
  318. * bn中记录了开括号的顺序, 再打印闭括号时将按该顺序打印
  319. */
  320. static char *codeToStr_(af_Code *code, LayerInt *layer, struct af_BlockEnd **bn) {
  321. char *re = charToStr(code->prefix);
  322. if (code->type == code_element) {
  323. if (checkElementData(code->element.data)) { // 需要|xx xx|语法
  324. re = strJoin(re, "|", true, false);
  325. re = strJoin(re, code->element.data, true, false);
  326. re = strJoin(re, "| ", true, false);
  327. } else
  328. re = strJoin(re, code->element.data, true, false);
  329. } else if (code->block.is_empty) {
  330. switch(code->block.type) {
  331. case parentheses:
  332. re = strJoin(re, "()", true, false);
  333. break;
  334. case brackets:
  335. re = strJoin(re, "[]", true, false);
  336. break;
  337. case curly:
  338. re = strJoin(re, "{}", true, false);
  339. break;
  340. default:
  341. break;
  342. }
  343. } else {
  344. char ch = NUL;
  345. switch(code->block.type) {
  346. case parentheses:
  347. re = strJoin(re, "(", true, false);
  348. ch = ')';
  349. break;
  350. case brackets:
  351. re = strJoin(re, "[", true, false);
  352. ch = ']';
  353. break;
  354. case curly:
  355. re = strJoin(re, "{", true, false);
  356. ch = '}';
  357. break;
  358. default:
  359. break;
  360. }
  361. auto new_bn = calloc(1, struct af_BlockEnd);
  362. new_bn->ch = ch;
  363. new_bn->next = *bn;
  364. *bn = new_bn;
  365. (*layer)++;
  366. }
  367. return re;
  368. }
  369. /*
  370. * 函数名: codeEndToStr
  371. * 目标: 转换闭括号为字符串
  372. */
  373. static char *codeEndToStr(CodeUInt code_end, LayerInt *layer, struct af_BlockEnd **bn) {
  374. char *re = NEW_STR(code_end);
  375. for (size_t i = 0; code_end > 0; code_end--, i++) {
  376. if (*bn == nullptr)
  377. break;
  378. (*layer)--;
  379. re[i] = (*bn)->ch;
  380. struct af_BlockEnd *tmp = (*bn)->next;
  381. free(*bn);
  382. *bn = tmp;
  383. }
  384. re = strJoin(re, " ", true, false);
  385. return re;
  386. }
  387. /*
  388. * 函数名: codeToStr
  389. * 目标: 转换n个元素(或n个函数调用)为code
  390. */
  391. char *codeToStr(af_Code *code, int n) {
  392. char *re = strCopy(nullptr);
  393. struct af_BlockEnd *bn = nullptr;
  394. LayerInt layer = 0;
  395. for(NULL; code != nullptr && layer >= 0 && (n > 0 || n == -1); code = code->next) {
  396. if (strlen(re) >= CODE_STR_MAX_SIZE) {
  397. re = strJoin(re, " ...", true, false); // 限度
  398. break;
  399. }
  400. re = strJoin(re, codeToStr_(code, &layer, &bn), true, true);
  401. if (code->code_end != 0)
  402. re = strJoin(re, codeEndToStr(code->code_end, &layer, &bn), true, true);
  403. if (n != -1 && layer == 0) /* 完成一个元素的打印 */
  404. n--;
  405. }
  406. return re;
  407. }
  408. static void printLayerSpace(size_t layer) {
  409. for (size_t i = 0; i < layer; i++)
  410. fputs(" ", stdout);
  411. }
  412. void printCode(af_Code *bt) {
  413. size_t layer = 0;
  414. for(NULL; bt != nullptr || layer < 0; bt = bt->next) {
  415. printLayerSpace(layer);
  416. layer = layer - bt->code_end;
  417. switch (bt->type) {
  418. case code_element:
  419. printf("element: [prefix (%c)] [end %u] [data '%s']\n", bt->prefix, bt->code_end, bt->element.data);
  420. break;
  421. case code_block:
  422. if (LAYER_ADD1(bt))
  423. layer++;
  424. printf("code: [prefix (%c)] [end %u] [type %c] [empty %d]\n", bt->prefix, bt->code_end, bt->block.type, bt->block.is_empty);
  425. break;
  426. default:
  427. printf("Unknown: [prefix (%c)] [end %u] [type %d]\n", bt->prefix, bt->code_end, bt->type);
  428. break;
  429. }
  430. }
  431. }
  432. enum af_CodeType getCodeType(af_Code *code) {
  433. return code->type;
  434. }
  435. enum af_BlockType getCodeBlockType(af_Code *code) {
  436. if (code->type != code_block)
  437. return (enum af_BlockType)'(';
  438. return code->block.type;
  439. }
  440. char getCodePrefix(af_Code *code) {
  441. return code->prefix;
  442. }
  443. CodeUInt getCodeEndCount(af_Code *code) {
  444. return code->code_end;
  445. }
  446. char *getCodeElementData(af_Code *code) {
  447. if (code->type != code_element)
  448. return nullptr;
  449. return code->element.data;
  450. }
  451. CodeUInt getCodeElementCount(af_Code *code) {
  452. if (!LAYER_ADD1(code))
  453. return 0;
  454. CodeUInt count;
  455. if (countElement(code->next, &count, nullptr) == 0)
  456. return 0;
  457. return count;
  458. }
  459. char *getCodeMD5(af_Code *code) {
  460. char *md5str = calloc(MD5_STR_LEN + 1, char);
  461. char md5_value[MD5_SIZE];
  462. MD5_CTX *md5 = MD5Init();
  463. for(NULL; code != nullptr; code = code->next) {
  464. char *tmp = nullptr;
  465. char head[] = {(char)code->type, code->prefix, 'x', 'x', NUL};
  466. char tail[512] = {0};
  467. if (code->prefix == NUL)
  468. head[1] = '-';
  469. if (code->type == code_block) {
  470. head[2] = code->block.is_empty ? 'e' : 'n';
  471. head[3] = code->block.type;
  472. } else
  473. tmp = strCopy(code->element.data);
  474. snprintf(tail, 512, "%d:%d", code->code_end, code->line);
  475. tmp = strJoin(head, tmp, false, true);
  476. tmp = strJoin(tmp, tail, true, false);
  477. MD5Update(md5, (unsigned char *)tmp, strlen((char *)tmp));
  478. free(tmp);
  479. }
  480. MD5Final(md5, (unsigned char *)md5_value);
  481. for(int i = 0; i < MD5_SIZE; i++)
  482. snprintf((char *)md5str + i * 2, 2 + 1, "%02x", md5_value[i]);
  483. return md5str;
  484. }
  485. static bool codeElementCheck(char *data) {
  486. if (data == nullptr)
  487. return false;
  488. return isCharUTF8(data);
  489. }
  490. /*
  491. * 函数名: codeSemanticCheck
  492. * 目标: 检查code结构体是否符合语义
  493. */
  494. bool codeSemanticCheck(af_Code *code) {
  495. CodeUInt layer = 0;
  496. if (code == nullptr || code->path == nullptr)
  497. return false;
  498. for(NULL; code != nullptr; code = code->next) {
  499. if (code->type != code_block && code->type != code_element)
  500. return false;
  501. if (code->type == code_element && !codeElementCheck(code->element.data))
  502. return false;
  503. if (code->type == code_block) {
  504. if (code->block.type != parentheses &&
  505. code->block.type != brackets && code->block.type != curly)
  506. return false;
  507. if (!code->block.is_empty && code->code_end != 0) // 正常情况下, block的code_end为0, 但empty时除外
  508. return false;
  509. }
  510. if (code->prefix != NUL && !strchr(ALL_PREFIX, code->prefix))
  511. return false;
  512. if (LAYER_ADD1(code))
  513. layer++;
  514. if (layer - code->code_end < 0)
  515. return false;
  516. layer -= code->code_end;
  517. }
  518. return true;
  519. }