123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605 |
- /*
- * 文件名: code.c
- * 目标: 管理Code结构体的函数
- */
- #include <cstdio>
- #include <cctype>
- #include "aFunCore.hpp"
- #include "tool.hpp"
- #include "__code.hpp"
- /* Code 创建函数 */
- static af_Code *makeCode(char prefix, FileLine line, ConstFilePath path);
- static af_Code *freeCode(af_Code *bt);
- /* Code 相关操作 */
- static int countElement(af_Code *element, CodeUInt *elements, af_Code **next);
- /* Code IO函数 */
- static bool readCode(af_Code **bt, af_Code *prev, FILE *file);
- static bool writeCode(af_Code *bt, FILE *file);
- /* Code 转换STR函数 */
- struct af_BlockEnd {
- char ch;
- struct af_BlockEnd *next;
- };
- static bool checkElementData(char *data);
- static char *codeToStr_(af_Code *code, LayerInt *layer, struct af_BlockEnd **bn);
- static char *codeEndToStr(CodeUInt code_end, LayerInt *layer, struct af_BlockEnd **bn);
- static af_Code *makeCode(char prefix, FileLine line, ConstFilePath path) {
- auto bt = calloc(1, af_Code);
- bt->line = line;
- bt->prefix = prefix;
- if (path != nullptr)
- bt->path = strCopy(path);
- return bt;
- }
- af_Code *makeElementCode(const char *var, char prefix, FileLine line, ConstFilePath path) {
- if (prefix != NUL && strchr(E_PREFIX, prefix) == nullptr)
- prefix = NUL;
- if (!isCharUTF8(var))
- return nullptr;
- af_Code *bt = makeCode(prefix, line, path);
- bt->type = code_element;
- bt->element.data = strCopy(var);
- return bt;
- }
- /* 判断该code是否令layer需要加1 */
- /* 即判定是否有子元素 */
- #define LAYER_ADD1(code) ((code)->type == code_block && !(code)->block.is_empty)
- /*
- * 函数名: countElement
- * 目标: 统计元素个数(不包括元素的子元素
- * 返回1 表示没有跳出过多层级
- * 返回2 表示跳出了过多层级
- * 返回0 表示错误
- */
- static int countElement(af_Code *element, CodeUInt *elements, af_Code **next) {
- CodeUInt layer = 0; // layer 是相对于当前element的层级数, 可能为负数
- af_Code *tmp = nullptr;
- if (next == nullptr)
- next = &tmp;
- for (*elements = 0; element != nullptr; *next = element, element = element->next) {
- if (layer == 0)
- (*elements)++;
- if (LAYER_ADD1(element))
- layer++;
- if (layer - element->code_end < 0)
- return 2;
- else
- layer = layer - element->code_end;
- }
- if (layer == 0)
- return 1;
- else // 大于0, 出现错误
- return 0;
- }
- af_Code *makeBlockCode(enum af_BlockType type, af_Code *element, char prefix, FileLine line, ConstFilePath path, af_Code **next) {
- af_Code *tmp = nullptr; // 保存最后一个code的地址
- CodeUInt elements = 0;
- if (next == nullptr)
- next = &tmp;
- if (prefix != NUL && strchr(B_PREFIX, prefix) == nullptr)
- prefix = NUL;
- if (countElement(element, &elements, next) != 1)
- return nullptr;
- af_Code *bt = makeCode(prefix, line, path);
- bt->type = code_block;
- bt->block.type = type;
- bt->next = element;
- if (elements == 0)
- bt->block.is_empty = true;
- else
- (*next)->code_end++; // 若 elements 不为 0, 则next指向最后一个元素
- return bt;
- }
- af_Code *pushCode(af_Code **base, af_Code *next) {
- af_Code *prev = nullptr;
- while ((*base) != nullptr) {
- prev = *base;
- base = &(prev->next);
- }
- next->prev = prev;
- *base = next;
- while (next != nullptr && next->next != nullptr)
- next = next->next;
- return next;
- }
- af_Code *copyAllCode(af_Code *base, ConstFilePath path) {
- af_Code *dest = nullptr;
- af_Code **pdest = &dest;
- af_Code *prev = nullptr;
- for(NULL; base != nullptr; base = base->next, prev = *pdest, pdest = &(prev->next)) {
- *pdest = makeCode(base->prefix, base->line, base->path);
- (*pdest)->type = base->type;
- (*pdest)->code_end = base->code_end;
- (*pdest)->prev = prev;
- switch (base->type) {
- case code_element:
- (*pdest)->element.data = strCopy(base->element.data);
- break;
- case code_block:
- (*pdest)->block.is_empty = base->block.is_empty;
- (*pdest)->block.type = base->block.type;
- break;
- default:
- break;
- }
- }
- if (dest != nullptr && path != nullptr) {
- free(dest->path);
- dest->path = strCopy(path);
- }
- return dest;
- }
- /*
- * 函数名: copyCode
- * 目标: 拷贝 code, 并为末尾的code设置合适的code_end
- */
- af_Code *copyCode(af_Code *base){
- af_Code *dest = nullptr;
- af_Code **pdest = &dest;
- af_Code *prev = nullptr;
- CodeUInt layer = 0;
- for(NULL; base != nullptr; base = base->next, prev = *pdest, pdest = &(prev->next)) {
- *pdest = makeCode(base->prefix, base->line, base->path);
- (*pdest)->type = base->type;
- (*pdest)->prev = prev;
- switch (base->type) {
- case code_element:
- (*pdest)->element.data = strCopy(base->element.data);
- break;
- case code_block:
- (*pdest)->block.is_empty = base->block.is_empty;
- (*pdest)->block.type = base->block.type;
- break;
- default:
- break;
- }
- if (LAYER_ADD1(base))
- layer++;
- if ((layer - base->code_end) < 0) { // base跳出layer, pdest不能按照base的code_end来, pdest只能刚好跳出layer
- (*pdest)->code_end = layer;
- break;
- } else { // 仍没跳出 layer
- (*pdest)->code_end = base->code_end;
- layer -= base->code_end;
- }
- }
- return dest;
- }
- static af_Code *freeCode(af_Code *bt) {
- af_Code *next = bt->next;
- free(bt->path);
- switch (bt->type) {
- case code_element:
- free(bt->element.data);
- break;
- default:
- break;
- }
- free(bt);
- return next;
- }
- void freeAllCode(af_Code *bt) {
- while (bt != nullptr)
- bt = freeCode(bt);
- }
- af_Code *getCodeNext(af_Code *bt) {
- if (!LAYER_ADD1(bt))
- return bt->code_end == 0 ? bt->next : nullptr;
- CodeUInt layer = 1;
- bt = bt->next; // 跳过第一个code_block
- while (bt != nullptr) {
- if (LAYER_ADD1(bt))
- layer++;
- if (layer - bt->code_end == 0) // layer为0表示迭代到该block的最后一个元素, 则该元素的下一个元素为该block的Next
- return bt->next;
- else if (layer - bt->code_end < 0) // 当layer小于0时, 认为已经无next, 即连续跳出了多层
- return nullptr;
- layer = layer - bt->code_end;
- bt = bt->next;
- }
- return nullptr;
- }
- af_Code *getCodeElement(af_Code *bt) {
- if (!LAYER_ADD1(bt))
- return nullptr;
- return bt->next;
- }
- #define Done(write) do{if(!(write)){return false;}}while(0)
- static bool writeCode(af_Code *bt, FILE *file) {
- Done(byteWriteUint_8(file, bt->type));
- Done(byteWriteUint_8(file, bt->prefix));
- Done(byteWriteUint_32(file, bt->line));
- Done(byteWriteUint_32(file, bt->code_end));
- switch (bt->type) {
- case code_element:
- Done(byteWriteStr(file, bt->element.data));
- break;
- case code_block:
- Done(byteWriteUint_8(file, bt->block.type));
- Done(byteWriteUint_8(file, bt->block.is_empty));
- break;
- default:
- break;
- }
- return true;
- }
- /*
- * 函数名: writeAllCode
- * 目标: 将Code写入字节码文件中
- * 备注: 写入字节码时不做语义检查, 在读取时最语义检查即可
- */
- bool writeAllCode(af_Code *bt, FILE *file) {
- if (bt == nullptr || bt->path == nullptr)
- return false;
- if (!codeSemanticCheck(bt))
- goto RETURN_FALSE;
- for(NULL; bt != nullptr; bt = bt->next) {
- if (!writeCode(bt, file))
- goto RETURN_FALSE;
- if (CLEAR_FERROR(stdin))
- goto RETURN_FALSE;
- Done(byteWriteUint_8(file, (bt->next == nullptr))); // 记录是否为最后一位
- }
- return true;
- RETURN_FALSE:
- return false;
- }
- static bool readCode(af_Code **bt, af_Code *prev, FILE *file) {
- uint8_t type;
- uint8_t prefix;
- uint32_t line;
- uint32_t code_end;
- Done(byteReadUint_8(file, &type));
- Done(byteReadUint_8(file, &prefix));
- Done(byteReadUint_32(file,&line));
- Done(byteReadUint_32(file, &code_end));
- *bt = makeCode((char)prefix, line, nullptr);
- (*bt)->type = (enum af_CodeType)type;
- (*bt)->code_end = (CodeUInt)code_end;
- (*bt)->prev = prev;
- switch (type) {
- case code_element:
- Done(byteReadStr(file, &((*bt)->element.data)));
- break;
- case code_block: {
- uint8_t block_type;
- uint8_t is_empty;
- Done(byteReadUint_8(file, &block_type));
- Done(byteReadUint_8(file,&is_empty));
- (*bt)->block.type = (enum af_BlockType)block_type;
- (*bt)->block.is_empty = (CodeUInt)is_empty;
- break;
- }
- default:
- break;
- }
- return true;
- }
- bool readAllCode(af_Code **bt, ConstFilePath path, FILE *file) {
- af_Code **base = bt;
- af_Code *prev = nullptr;
- *bt = nullptr;
- for(NULL; true;prev = *bt, bt = &(prev->next)) {
- if(!readCode(bt, prev, file))
- goto RETURN_FALSE;
- if (CLEAR_FERROR(stdin))
- goto RETURN_FALSE;
- uint8_t last;
- Done(byteReadUint_8(file, &last));
- if (last)
- break;
- }
- if (*base != nullptr && path != nullptr)
- (*base)->path = strCopy(path);
- if (!codeSemanticCheck(*base))
- goto RETURN_FALSE;
- return true;
- RETURN_FALSE:
- freeAllCode(*bt);
- *bt = nullptr;
- return false;
- }
- /*
- * 函数名: checkElementData
- * 目标: 检查element中data字符串是否有空白符
- */
- static bool checkElementData(char *data) {
- for (char *ch = data; *ch != NUL; ch++) {
- if (isspace(*ch) || *ch == '\n')
- return true;
- }
- return false;
- }
- /*
- * 函数名: codeEndToStr
- * 目标: 转换element或开括号为字符串
- * 若遇到开括号则设定bn, 并且设定layer
- *
- * bn中记录了开括号的顺序, 再打印闭括号时将按该顺序打印
- */
- static char *codeToStr_(af_Code *code, LayerInt *layer, struct af_BlockEnd **bn) {
- char *re = charToStr(code->prefix);
- if (code->type == code_element) {
- if (checkElementData(code->element.data)) { // 需要|xx xx|语法
- re = strJoin(re, "|", true, false);
- re = strJoin(re, code->element.data, true, false);
- re = strJoin(re, "| ", true, false);
- } else
- re = strJoin(re, code->element.data, true, false);
- } else if (code->block.is_empty) {
- switch(code->block.type) {
- case parentheses:
- re = strJoin(re, "()", true, false);
- break;
- case brackets:
- re = strJoin(re, "[]", true, false);
- break;
- case curly:
- re = strJoin(re, "{}", true, false);
- break;
- default:
- break;
- }
- } else {
- char ch = NUL;
- switch(code->block.type) {
- case parentheses:
- re = strJoin(re, "(", true, false);
- ch = ')';
- break;
- case brackets:
- re = strJoin(re, "[", true, false);
- ch = ']';
- break;
- case curly:
- re = strJoin(re, "{", true, false);
- ch = '}';
- break;
- default:
- break;
- }
- auto new_bn = calloc(1, struct af_BlockEnd);
- new_bn->ch = ch;
- new_bn->next = *bn;
- *bn = new_bn;
- (*layer)++;
- }
- return re;
- }
- /*
- * 函数名: codeEndToStr
- * 目标: 转换闭括号为字符串
- */
- static char *codeEndToStr(CodeUInt code_end, LayerInt *layer, struct af_BlockEnd **bn) {
- char *re = NEW_STR(code_end);
- for (size_t i = 0; code_end > 0; code_end--, i++) {
- if (*bn == nullptr)
- break;
- (*layer)--;
- re[i] = (*bn)->ch;
- struct af_BlockEnd *tmp = (*bn)->next;
- free(*bn);
- *bn = tmp;
- }
- re = strJoin(re, " ", true, false);
- return re;
- }
- /*
- * 函数名: codeToStr
- * 目标: 转换n个元素(或n个函数调用)为code
- */
- char *codeToStr(af_Code *code, int n) {
- char *re = strCopy(nullptr);
- struct af_BlockEnd *bn = nullptr;
- LayerInt layer = 0;
- for(NULL; code != nullptr && layer >= 0 && (n > 0 || n == -1); code = code->next) {
- if (strlen(re) >= CODE_STR_MAX_SIZE) {
- re = strJoin(re, " ...", true, false); // 限度
- break;
- }
- re = strJoin(re, codeToStr_(code, &layer, &bn), true, true);
- if (code->code_end != 0)
- re = strJoin(re, codeEndToStr(code->code_end, &layer, &bn), true, true);
- if (n != -1 && layer == 0) /* 完成一个元素的打印 */
- n--;
- }
- return re;
- }
- static void printLayerSpace(size_t layer) {
- for (size_t i = 0; i < layer; i++)
- fputs(" ", stdout);
- }
- void printCode(af_Code *bt) {
- size_t layer = 0;
- for(NULL; bt != nullptr || layer < 0; bt = bt->next) {
- printLayerSpace(layer);
- layer = layer - bt->code_end;
- switch (bt->type) {
- case code_element:
- printf("element: [prefix (%c)] [end %u] [data '%s']\n", bt->prefix, bt->code_end, bt->element.data);
- break;
- case code_block:
- if (LAYER_ADD1(bt))
- layer++;
- printf("code: [prefix (%c)] [end %u] [type %c] [empty %d]\n", bt->prefix, bt->code_end, bt->block.type, bt->block.is_empty);
- break;
- default:
- printf("Unknown: [prefix (%c)] [end %u] [type %d]\n", bt->prefix, bt->code_end, bt->type);
- break;
- }
- }
- }
- enum af_CodeType getCodeType(af_Code *code) {
- return code->type;
- }
- enum af_BlockType getCodeBlockType(af_Code *code) {
- if (code->type != code_block)
- return (enum af_BlockType)'(';
- return code->block.type;
- }
- char getCodePrefix(af_Code *code) {
- return code->prefix;
- }
- CodeUInt getCodeEndCount(af_Code *code) {
- return code->code_end;
- }
- char *getCodeElementData(af_Code *code) {
- if (code->type != code_element)
- return nullptr;
- return code->element.data;
- }
- CodeUInt getCodeElementCount(af_Code *code) {
- if (!LAYER_ADD1(code))
- return 0;
- CodeUInt count;
- if (countElement(code->next, &count, nullptr) == 0)
- return 0;
- return count;
- }
- char *getCodeMD5(af_Code *code) {
- char *md5str = calloc(MD5_STR_LEN + 1, char);
- char md5_value[MD5_SIZE];
- MD5_CTX *md5 = MD5Init();
- for(NULL; code != nullptr; code = code->next) {
- char *tmp = nullptr;
- char head[] = {(char)code->type, code->prefix, 'x', 'x', NUL};
- char tail[512] = {0};
- if (code->prefix == NUL)
- head[1] = '-';
- if (code->type == code_block) {
- head[2] = code->block.is_empty ? 'e' : 'n';
- head[3] = code->block.type;
- } else
- tmp = strCopy(code->element.data);
- snprintf(tail, 512, "%d:%d", code->code_end, code->line);
- tmp = strJoin(head, tmp, false, true);
- tmp = strJoin(tmp, tail, true, false);
- MD5Update(md5, (unsigned char *)tmp, strlen((char *)tmp));
- free(tmp);
- }
- MD5Final(md5, (unsigned char *)md5_value);
- for(int i = 0; i < MD5_SIZE; i++)
- snprintf((char *)md5str + i * 2, 2 + 1, "%02x", md5_value[i]);
- return md5str;
- }
- static bool codeElementCheck(char *data) {
- if (data == nullptr)
- return false;
- return isCharUTF8(data);
- }
- /*
- * 函数名: codeSemanticCheck
- * 目标: 检查code结构体是否符合语义
- */
- bool codeSemanticCheck(af_Code *code) {
- CodeUInt layer = 0;
- if (code == nullptr || code->path == nullptr)
- return false;
- for(NULL; code != nullptr; code = code->next) {
- if (code->type != code_block && code->type != code_element)
- return false;
- if (code->type == code_element && !codeElementCheck(code->element.data))
- return false;
- if (code->type == code_block) {
- if (code->block.type != parentheses &&
- code->block.type != brackets && code->block.type != curly)
- return false;
- if (!code->block.is_empty && code->code_end != 0) // 正常情况下, block的code_end为0, 但empty时除外
- return false;
- }
- if (code->prefix != NUL && !strchr(ALL_PREFIX, code->prefix))
- return false;
- if (LAYER_ADD1(code))
- layer++;
- if (layer - code->code_end < 0)
- return false;
- layer -= code->code_end;
- }
- return true;
- }
|