From 1b360090396cea224477ee45c6016e04019b8c45 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Wed, 12 Aug 2026 15:15:42 +0800 Subject: [PATCH] 1, support recursive macro, 2, support fprintf() of musl-libc & global var of *.so, 3, fix: parse error for number expr with '()' of func ptr array. --- core/scf_lex_word.h | 2 + elf/scf_elf_link.c | 2 +- examples/c_func_ptr_arg2.c | 7 + examples/fprintf.c | 7 + examples/macro_recursive.c | 12 ++ lex/scf_lex.c | 40 ++-- lex/scf_lex_util.c | 49 +++-- lex/scf_macro.c | 294 ++++++++++++++++++++---------- parse/scf_dfa.c | 41 ++++- parse/scf_dfa.h | 5 + parse/scf_dfa_function.c | 10 +- parse/scf_dfa_var.c | 4 + parse/scf_operator_handler_expr.c | 13 +- 13 files changed, 348 insertions(+), 138 deletions(-) create mode 100644 examples/c_func_ptr_arg2.c create mode 100644 examples/fprintf.c create mode 100644 examples/macro_recursive.c diff --git a/core/scf_lex_word.h b/core/scf_lex_word.h index 54eeaea..f8f6f07 100644 --- a/core/scf_lex_word.h +++ b/core/scf_lex_word.h @@ -257,6 +257,8 @@ struct scf_lex_word_s scf_string_t* file; // original code file name int line; // line in the code file above int pos; // position in the line above + + uint8_t macro_used_flag:1; }; static inline int scf_lex_is_identity(scf_lex_word_t* w) diff --git a/elf/scf_elf_link.c b/elf/scf_elf_link.c index d60d32e..1b62609 100644 --- a/elf/scf_elf_link.c +++ b/elf/scf_elf_link.c @@ -985,7 +985,7 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* else rela->r_info = ELF32_R_INFO(j + 1, ELF32_R_TYPE(rela->r_info)); - scf_logi("j: %d, sym: %s, r_offset: %#lx, r_addend: %ld, got_flag: %d\n", j, + scf_logd("j: %d, sym: %s, r_offset: %#lx, r_addend: %ld, got_flag: %d\n", j, sym->name, rela->r_offset, rela->r_addend, got_flag); } diff --git a/examples/c_func_ptr_arg2.c b/examples/c_func_ptr_arg2.c new file mode 100644 index 0000000..e8e8cf9 --- /dev/null +++ b/examples/c_func_ptr_arg2.c @@ -0,0 +1,7 @@ + +int (*add_array_pt[1 + (2 + 1)])(int* array, int n, int (*add_pt)(int a, int b)); + +int main() +{ + return 0; +} diff --git a/examples/fprintf.c b/examples/fprintf.c new file mode 100644 index 0000000..30f5641 --- /dev/null +++ b/examples/fprintf.c @@ -0,0 +1,7 @@ +#include + +int main() +{ + fprintf(stdout, "hello world\n"); + return 0; +} diff --git a/examples/macro_recursive.c b/examples/macro_recursive.c new file mode 100644 index 0000000..789b34d --- /dev/null +++ b/examples/macro_recursive.c @@ -0,0 +1,12 @@ +int printf(const char* fmt, ...); + +#define A (B) +#define B (A) + +int main() +{ + int A = 1; + + printf("A: %d\n", A); + return 0; +} diff --git a/lex/scf_lex.c b/lex/scf_lex.c index 26dcbd3..37e57d5 100644 --- a/lex/scf_lex.c +++ b/lex/scf_lex.c @@ -355,7 +355,6 @@ static int _lex_minus(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) return 0; } - static int _lex_number(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) { scf_lex_word_t* w = NULL; @@ -363,6 +362,7 @@ static int _lex_number(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) scf_char_t* c1 = NULL; scf_char_t* c2 = NULL; + int pos = lex->pos; int ret = 0; if ('0' == c0->c) { @@ -398,7 +398,7 @@ static int _lex_number(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) _lex_push_char(lex, c1); if (c1->c < '0' || c1->c > '9') { // is 0 - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_INT); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_INT); w->data.u64 = atoi(s->data); w->text = s; @@ -430,6 +430,8 @@ static int _lex_identity(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) { scf_string_t* s = scf_string_cstr_len(c0->utf8, c0->len); + int pos = lex->pos; + lex->pos += c0->len; free(c0); c0 = NULL; @@ -456,33 +458,33 @@ static int _lex_identity(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) if (SCF_CSTR_CMP(s, "NULL")) { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_U64); if (w) w->data.u64 = 0; } else if (SCF_CSTR_CMP(s, "__LINE__")) { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_U64); if (w) w->data.u64 = lex->nb_lines; } else if (SCF_CSTR_CMP(s, "__FILE__")) { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_STRING); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_STRING); if (w) w->data.s = scf_string_clone(lex->file); } else if (SCF_CSTR_CMP(s, "__func__")) { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_STRING); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_STRING); } else { int type = _find_key_word(s); if (-1 == type) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_ID); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_ID); else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, type); } if (w) @@ -507,6 +509,8 @@ static int _lex_char(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) scf_char_t* c2 = _lex_pop_char(lex); scf_char_t* c3; + int pos = lex->pos; + if ('\\' == c1->c) { c3 = _lex_pop_char(lex); @@ -517,7 +521,7 @@ static int _lex_char(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) scf_string_cat_cstr_len(s, c2->utf8, c2->len); scf_string_cat_cstr_len(s, c3->utf8, 1); - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_CHAR); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_CHAR); w->data.i64 = _find_escape_char(c2->c); lex->pos += c2->len + 3; @@ -533,7 +537,7 @@ static int _lex_char(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) scf_string_cat_cstr_len(s, c1->utf8, c1->len); scf_string_cat_cstr_len(s, c2->utf8, 1); - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_CHAR); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_CHAR); w->data.i64 = c1->c; lex->pos += c1->len + 2; @@ -558,13 +562,15 @@ static int _lex_string(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) scf_string_t* s = scf_string_cstr_len(c0->utf8, 1); scf_string_t* d = scf_string_alloc(); + int pos = lex->pos; + while (1) { scf_char_t* c1 = _lex_pop_char(lex); if ('\"' == c1->c) { scf_string_cat_cstr_len(s, c1->utf8, 1); - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_STRING); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_STRING); w->data.s = d; w->text = s; d = NULL; @@ -695,6 +701,8 @@ static void _lex_drop_to(scf_lex_t* lex, int c0, int c1) free(c); c = NULL; + lex->pos++; + if ('\n' == tmp) { lex->nb_lines++; lex->pos = 0; @@ -707,6 +715,13 @@ static void _lex_drop_to(scf_lex_t* lex, int c0, int c1) c = _lex_pop_char(lex); if (c1 == c->c) { + lex->pos++; + + if ('\n' == c1) { + lex->nb_lines++; + lex->pos = 0; + } + free(c); c = NULL; break; @@ -755,6 +770,7 @@ int __lex_pop_word(scf_lex_t* lex, scf_lex_word_t** pword) || '\r' == c->c || '\t' == c->c || ' ' == c->c || '\\' == c->c) { + int pos = lex->pos; int type = -1; if ('\n' == c->c) { @@ -771,7 +787,7 @@ int __lex_pop_word(scf_lex_t* lex, scf_lex_word_t** pword) } if (type > 0) { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, type); if (SCF_LEX_WORD_LF == type) w->text = scf_string_cstr("LF"); diff --git a/lex/scf_lex_util.c b/lex/scf_lex_util.c index a6360e2..076641b 100644 --- a/lex/scf_lex_util.c +++ b/lex/scf_lex_util.c @@ -246,6 +246,7 @@ int _lex_number_base_10(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) scf_char_t* c3; scf_lex_word_t* w; + int pos = lex->pos; int type = -1; int dot = 0; int exp = 0; @@ -339,20 +340,20 @@ next: if (exp > 0 || dot > 0) { if (SCF_LEX_WORD_CONST_FLOAT == type) { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_FLOAT); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_FLOAT); w->data.f = atof(s->data); } else { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_DOUBLE); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_DOUBLE); w->data.d = atof(s->data); } } else { if (type > 0) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, type); else if (value & ~0xffffffffULL) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_U64); else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_U32); w->data.u64 = value; } @@ -373,6 +374,7 @@ int _lex_number_base_16(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) scf_char_t* c2; scf_lex_word_t* w; + int pos = lex->pos; int type = -1; uint64_t value = 0; @@ -431,12 +433,12 @@ next: } if (type > 0) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, type); else if (value & ~0xffffffffULL) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_U64); else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_U32); w->data.u64 = value; @@ -456,6 +458,7 @@ int _lex_number_base_8(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) scf_char_t* c2; scf_lex_word_t* w; + int pos = lex->pos; int type = -1; uint64_t value = 0; @@ -515,12 +518,13 @@ next: } if (type > 0) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, type); else if (value & ~0xffffffffULL) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_U64); else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_U32); + w->data.u64 = value; w->text = s; @@ -539,6 +543,7 @@ int _lex_number_base_2(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) scf_char_t* c2; scf_lex_word_t* w; + int pos = lex->pos; int type = -1; uint64_t value = 0; @@ -598,12 +603,13 @@ next: } if (type > 0) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, type); else if (value & ~0xffffffffULL) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_U64); else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_U32); + w->data.u64 = value; w->text = s; @@ -622,6 +628,7 @@ int _lex_double(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) scf_char_t* c2; scf_lex_word_t* w; + int pos = lex->pos; int type = -1; char postfix[8]; int n = 0; @@ -675,10 +682,10 @@ next: } if (SCF_LEX_WORD_CONST_FLOAT == type) { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_FLOAT); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_FLOAT); w->data.f = atof(s->data); } else { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_DOUBLE); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_DOUBLE); w->data.d = atof(s->data); } @@ -698,6 +705,8 @@ int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) scf_lex_word_t* w = NULL; scf_string_t* s = scf_string_cstr_len(c0->utf8, c0->len); + int pos = lex->pos; + lex->pos += c0->len; free(c0); @@ -719,11 +728,11 @@ int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) free(c2); c2 = NULL; - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_VA_ARGS); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_VA_ARGS); w->text = s; s = NULL; } else { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_RANGE); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_RANGE); w->text = s; s = NULL; @@ -758,7 +767,7 @@ int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) return -EINVAL; } - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, type); if (!w) { scf_string_free(s); return -ENOMEM; @@ -775,7 +784,7 @@ int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) if ('0' <= tmp && '9' >= tmp) // for double / float .5, .618, etc. return _lex_double(lex, pword, s); - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_DOT); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_DOT); w->text = s; s = NULL; } diff --git a/lex/scf_macro.c b/lex/scf_macro.c index e85a408..c547825 100644 --- a/lex/scf_macro.c +++ b/lex/scf_macro.c @@ -1,4 +1,5 @@ #include"scf_lex.h" +#include"scf_stack.h" scf_macro_t* __find_macro(scf_lex_t* lex, scf_lex_word_t* w) { @@ -341,6 +342,8 @@ int __parse_macro_define(scf_lex_t* lex, int def_flag) w->next = NULL; + scf_logi("'%s' in file: %s, line: %d\n", w->text->data, w->file->data, w->line); + *pp = w; pp = &w->next; w = NULL; @@ -570,12 +573,40 @@ int __parse_macro_ifdef(scf_lex_t* lex, int def_flag) return __do_macro_if(lex, found == def_flag); } -static int __fill_macro_argv(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use, scf_vector_t* argv) +static int __get_macro_argv(scf_lex_t* lex, scf_lex_word_t** h, scf_lex_word_t** w) +{ + if (h) { + if (!*h) + return -EINVAL; + + *w = *h; + *h = (*h)->next; + return 0; + } + + return __lex_pop_word(lex, w); +} + +static void __clear_macro_argv(scf_vector_t* argv) +{ + scf_lex_word_t* w; + int i; + + for (i = 0; i < argv->size; i++) { + w = argv->data[i]; + + scf_slist_clear(w, scf_lex_word_t, next, scf_lex_word_free); + } + + argv->size = 0; +} + +static int __fill_macro_argv(scf_lex_t* lex, scf_lex_word_t** h, scf_macro_t* m, scf_lex_word_t* use, scf_vector_t* argv) { scf_lex_word_t** pp; scf_lex_word_t* w = NULL; - int ret = __lex_pop_word(lex, &w); + int ret = __get_macro_argv(lex, h, &w); if (ret < 0) return ret; @@ -590,12 +621,11 @@ static int __fill_macro_argv(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use int n_lps = 0; int n_rps = 0; - int i; pp = NULL; while (1) { - ret = __lex_pop_word(lex, &w); + ret = __get_macro_argv(lex, h, &w); if (ret < 0) return ret; @@ -604,8 +634,9 @@ static int __fill_macro_argv(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use scf_loge("unexpected ',' in macro '%s', file: %s, line: %d\n", m->w->text->data, w->file->data, w->line); scf_lex_word_free(w); - ret = -1; - goto error; + + __clear_macro_argv(argv); + return -1; } w->next = NULL; @@ -637,7 +668,9 @@ static int __fill_macro_argv(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use ret = scf_vector_add(argv, w); if (ret < 0) { scf_lex_word_free(w); - goto error; + + __clear_macro_argv(argv); + return ret; } } @@ -650,20 +683,12 @@ static int __fill_macro_argv(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use scf_loge("macro '%s' needs %d args, but in fact give %d args, file: %s, line: %d\n", m->w->text->data, m->argv->size, argv->size, use->file->data, use->line); - ret = -1; - goto error; - } - - return 0; -error: - for (i = 0; i < argv->size; i++) { - w = argv->data[i]; - scf_slist_clear(w, scf_lex_word_t, next, scf_lex_word_free); + __clear_macro_argv(argv); + return -1; } - argv->size = 0; - return ret; + return 0; } static int __convert_str(scf_lex_word_t* h) @@ -711,28 +736,14 @@ static int __convert_str(scf_lex_word_t* h) return 0; } -static int __use_macro(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use) +static int __use_macro(scf_lex_word_t** ph, scf_lex_t* lex, scf_macro_t* m, scf_vector_t* argv, scf_lex_word_t* use) { scf_lex_word_t** pp; + scf_lex_word_t* h = NULL; scf_lex_word_t* p; - scf_lex_word_t* h; scf_lex_word_t* w; scf_lex_word_t* prev; - scf_vector_t* argv = NULL; - - if (m->argv) { - argv = scf_vector_alloc(); - if (!argv) - return -ENOMEM; - int ret = __fill_macro_argv(lex, m, use, argv); - if (ret < 0) { - scf_vector_free(argv); - return ret; - } - } - - h = NULL; pp = &h; int ret = 0; @@ -746,7 +757,7 @@ static int __use_macro(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use) continue; } - scf_logd("p: '%s', line: %d:%d, hash: %d\n", p->text->data, p->line, p->pos, hash); + scf_logi("p: '%s', line: %d:%d, hash: %d\n", p->text->data, p->line, p->pos, hash); if (m->argv) { assert(argv); @@ -825,17 +836,6 @@ static int __use_macro(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use) } error: - if (argv) { - for (i = 0; i < argv->size; i++) { - w = argv->data[i]; - - if (w) - scf_slist_clear(w, scf_lex_word_t, next, scf_lex_word_free); - } - - scf_vector_free(argv); - argv = NULL; - } if (ret < 0) { scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free); @@ -868,6 +868,37 @@ error: continue; } + } else if (SCF_LEX_WORD_HASH2 == w1->type) { + w2 = w1->next; + + if (SCF_LEX_WORD_ID != w->type) { + scf_loge("%s:%d:%d, needs identity before '##'\n", w->file->data, w->line, w->pos); + + scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free); + return -EINVAL; + } + + if (!w2 || SCF_LEX_WORD_ID != w2->type) { + scf_loge("%s:%d:%d, needs identity after '##'\n", w1->file->data, w1->line, w1->pos); + + scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free); + return -EINVAL; + } + + ret = scf_string_cat(w->text, w2->text); + if (ret < 0) { + scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free); + return ret; + } + + w->next = w2->next; + + scf_lex_word_free(w1); + scf_lex_word_free(w2); + w1 = NULL; + w2 = NULL; + continue; + } else if (SCF_LEX_WORD_COMMA == w1->type) { w2 = w1->next; @@ -892,7 +923,7 @@ error: w = w->next; } -#if 0 +#if 1 w = h; while (w) { scf_logi("---------- %s, line: %d\n", w->text->data, w->line); @@ -900,81 +931,152 @@ error: } #endif - *pp = lex->word_list; - lex->word_list = h; + *ph = h; return 0; } -static int __use_hash2(scf_lex_t* lex, scf_lex_word_t* prev) +static int _find_used_macro(const void* v0, const void* v1) { - scf_lex_word_t* after = NULL; - - int ret = __lex_pop_word(lex, &after); - if (ret < 0) - return ret; - - switch (after->type) { - - case SCF_LEX_WORD_ID: - ret = scf_string_cat(prev->text, after->text); - break; - - default: - ret = -1; - scf_loge("needs identity after '##', file: %s, line: %d\n", after->file->data, after->line); - break; - }; + const scf_macro_t* m0 = v0; + const scf_macro_t* m1 = v1; - scf_lex_word_free(after); - return ret; + return scf_string_cmp(m0->w->text, m1->w->text); } -int __lex_use_macro(scf_lex_t* lex, scf_lex_word_t** pp) +static int __recursive_use_macro(scf_lex_t* lex, scf_lex_word_t** h, scf_stack_t* used_macros) { - scf_lex_word_t* w1 = NULL; - scf_lex_word_t* w = *pp; - scf_macro_t* m; + scf_lex_word_t** pp = h; + scf_lex_word_t* w; + scf_macro_t* m; - *pp = NULL; + while (*pp) { + w = *pp; - while (SCF_LEX_WORD_ID == w->type) { + if (SCF_LEX_WORD_ID != w->type) { + pp = &w->next; + continue; + } m = __find_macro(lex, w); - if (m) { - int ret = __use_macro(lex, m, w); - scf_lex_word_free(w); - w = NULL; - if (ret < 0) - return ret; - - ret = __lex_pop_word(lex, &w); - if (ret < 0) - return ret; + if (!m || scf_vector_find_cmp(used_macros, m, _find_used_macro)) { + pp = &w->next; continue; } - int ret = __lex_pop_word(lex, &w1); - if (ret < 0) { - scf_lex_word_free(w); + int ret = scf_stack_push(used_macros, m); + if (ret < 0) return ret; + + scf_lex_word_t* h_res = NULL; + scf_lex_word_t* h_next = w->next; + scf_vector_t* argv = NULL; + + w->next = NULL; + + if (m->argv) { + argv = scf_vector_alloc(); + if (!argv) { + scf_slist_clear(h_next, scf_lex_word_t, next, scf_lex_word_free); + return -ENOMEM; + } + + if (used_macros->size > 1) + ret = __fill_macro_argv(lex, &h_next, m, w, argv); + else + ret = __fill_macro_argv(lex, NULL, m, w, argv); + + if (ret < 0) { + scf_loge("macro '%s', m->argv->size: %d\n", m->w->text->data, m->argv->size); + + scf_vector_free(argv); + scf_slist_clear(h_next, scf_lex_word_t, next, scf_lex_word_free); + return ret; + } } - if (SCF_LEX_WORD_HASH2 != w1->type) { - scf_lex_push_word(lex, w1); - break; + ret = __use_macro(&h_res, lex, m, argv, w); + + if (argv) { + __clear_macro_argv(argv); + + scf_vector_free(argv); + argv = NULL; } - scf_lex_word_free(w1); - w1 = NULL; + if (ret < 0) { + scf_slist_clear(h_next, scf_lex_word_t, next, scf_lex_word_free); + return ret; + } - ret = __use_hash2(lex, w); + ret = __recursive_use_macro(lex, &h_res, used_macros); if (ret < 0) { - scf_lex_word_free(w); + scf_slist_clear(h_res, scf_lex_word_t, next, scf_lex_word_free); + scf_slist_clear(h_next, scf_lex_word_t, next, scf_lex_word_free); return ret; } + + *pp = h_res; + + while (*pp) + pp = &(*pp)->next; + + *pp = h_next; + + h_res = NULL; + h_next = NULL; + + scf_lex_word_free(w); + w = NULL; + + scf_stack_pop(used_macros); } - *pp = w; return 0; } + +int __lex_use_macro(scf_lex_t* lex, scf_lex_word_t** pp) +{ + scf_stack_t* used_macros; + scf_lex_word_t* w = *pp; + + if (SCF_LEX_WORD_ID != w->type + || w->macro_used_flag + || !__find_macro(lex, w)) + return 0; + + *pp = NULL; + w->next = NULL; + + used_macros = scf_stack_alloc(); + if (!used_macros) { + scf_lex_word_free(w); + return -ENOMEM; + } + + int ret = __recursive_use_macro(lex, &w, used_macros); + + scf_stack_free(used_macros); + used_macros = NULL; + + if (ret < 0) { + scf_slist_clear(w, scf_lex_word_t, next, scf_lex_word_free); + return ret; + } + + scf_lex_word_t** tail = &w; + scf_lex_word_t* w2; + + while (*tail) { + w2 = *tail; + + w2->macro_used_flag = 1; + + tail = &w2->next; + } + + *tail = lex->word_list; + lex->word_list = w; + + return __lex_pop_word(lex, pp); +} diff --git a/parse/scf_dfa.c b/parse/scf_dfa.c index ded7114..b8b8fb2 100644 --- a/parse/scf_dfa.c +++ b/parse/scf_dfa.c @@ -4,6 +4,30 @@ static int _scf_dfa_node_parse_word(scf_dfa_t* dfa, scf_dfa_node_t* node, scf_vector_t* words, void* data, int pre_hook_flag); +void scf_dfa_disable_hook(scf_dfa_hook_t* h, const char* name) +{ + while (h) { + if (!strcmp(name, h->node->name)) { + h->disable_flag = 1; + break; + } + + h = h->next; + } +} + +void scf_dfa_enable_hook(scf_dfa_hook_t* h, const char* name) +{ + while (h) { + if (!strcmp(name, h->node->name)) { + h->disable_flag = 0; + break; + } + + h = h->next; + } +} + void scf_dfa_del_hook_by_name(scf_dfa_hook_t** pp, const char* name) { while (*pp) { @@ -230,20 +254,25 @@ static int _scf_dfa_childs_parse_word(scf_dfa_t* dfa, scf_dfa_node_t** childs, i { assert(words->size > 0); + scf_dfa_node_t* child; + scf_lex_word_t* w; + scf_dfa_hook_t* hook; int i; + for (i = 0; i < nb_childs; i++) { - scf_dfa_node_t* child = childs[i]; - scf_lex_word_t* w = words->data[words->size - 1]; + child = childs[i]; + w = words->data[words->size - 1]; scf_logd("i: %d, nb_childs: %d, child: %s, w: %s\n", i, nb_childs, child->name, w->text->data); int pre_hook_flag = 0; - scf_dfa_hook_t* hook = scf_dfa_find_hook(dfa, &(dfa->hooks[SCF_DFA_HOOK_PRE]), w); - if (hook) { - // if pre hook is set, deliver the word to the proper hook node. - if (hook->node != child) + hook = scf_dfa_find_hook(dfa, &(dfa->hooks[SCF_DFA_HOOK_PRE]), w); + + if (hook && !hook->disable_flag) { + + if (hook->node != child) // if pre hook is set, deliver the word to the proper hook node. continue; pre_hook_flag = 1; diff --git a/parse/scf_dfa.h b/parse/scf_dfa.h index d261f9d..a5ccd7d 100644 --- a/parse/scf_dfa.h +++ b/parse/scf_dfa.h @@ -39,6 +39,8 @@ struct scf_dfa_hook_s { scf_dfa_hook_t* next; scf_dfa_node_t* node; + + uint8_t disable_flag:1; }; struct scf_dfa_node_s @@ -163,4 +165,7 @@ int scf_dfa_parse_word(scf_dfa_t* dfa, void* word, void* dat void scf_dfa_del_hook (scf_dfa_hook_t** pp, scf_dfa_hook_t* sentinel); void scf_dfa_del_hook_by_name(scf_dfa_hook_t** pp, const char* name); +void scf_dfa_disable_hook(scf_dfa_hook_t* h, const char* name); +void scf_dfa_enable_hook (scf_dfa_hook_t* h, const char* name); + #endif diff --git a/parse/scf_dfa_function.c b/parse/scf_dfa_function.c index b9e0011..2ac87de 100644 --- a/parse/scf_dfa_function.c +++ b/parse/scf_dfa_function.c @@ -402,7 +402,7 @@ static int _function_action_pf_rp(scf_dfa_t* dfa, scf_vector_t* words, void* dat if (id && id->identity) scf_logw("pf: %s(), nb_pointers: %d\n", id->identity->text->data, d->pf_pointers); } else { - SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_pf_rp"), SCF_DFA_HOOK_PRE); +// SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_pf_rp"), SCF_DFA_HOOK_PRE); } return SCF_DFA_NEXT_WORD; @@ -679,6 +679,8 @@ static int _dfa_init_syntax_function(scf_dfa_t* dfa) SCF_DFA_GET_MODULE_NODE(dfa, var, ls, ls); SCF_DFA_GET_MODULE_NODE(dfa, var, rs, rs); SCF_DFA_GET_MODULE_NODE(dfa, var, assign, assign); + SCF_DFA_GET_MODULE_NODE(dfa, var, comma, var_comma); + SCF_DFA_GET_MODULE_NODE(dfa, var, semicolon, semicolon); // function pointer scf_dfa_node_add_child(base_type, pf_lp); @@ -697,6 +699,12 @@ static int _dfa_init_syntax_function(scf_dfa_t* dfa) scf_dfa_node_add_child(pf_lp, pf_lp); scf_dfa_node_add_child(pf_rp, pf_rp); + // var with (), such as 'int (v) = 1;' + scf_dfa_node_add_child(pf_lp, identity); + scf_dfa_node_add_child(pf_rp, assign); + scf_dfa_node_add_child(pf_rp, var_comma); + scf_dfa_node_add_child(pf_rp, semicolon); + scf_dfa_node_add_child(pf_rp, lp); // function start diff --git a/parse/scf_dfa_var.c b/parse/scf_dfa_var.c index 8e8c083..7f90287 100644 --- a/parse/scf_dfa_var.c +++ b/parse/scf_dfa_var.c @@ -506,6 +506,8 @@ static int _var_action_ls(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->nb_lss++; + scf_dfa_disable_hook(dfa->hooks[SCF_DFA_HOOK_PRE], "function_pf_rp"); + return SCF_DFA_NEXT_WORD; } @@ -520,6 +522,8 @@ static int _var_action_rs(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_logd("d->expr: %p\n", d->expr); + scf_dfa_enable_hook(dfa->hooks[SCF_DFA_HOOK_PRE], "function_pf_rp"); + if (!d->expr) return SCF_DFA_SWITCH_TO; diff --git a/parse/scf_operator_handler_expr.c b/parse/scf_operator_handler_expr.c index 2976c51..4606422 100644 --- a/parse/scf_operator_handler_expr.c +++ b/parse/scf_operator_handler_expr.c @@ -136,6 +136,10 @@ static int _scf_op_expr_expr(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, v return -1; } + scf_variable_t* v = _scf_operand_get(n); + if (v) + parent->result = scf_variable_ref(v); + return 0; } @@ -281,9 +285,8 @@ static int _scf_op_expr_binary(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, if (scf_type_is_number(v0->type) && scf_type_is_number(v1->type)) { - if (!scf_variable_const(v0) || !scf_variable_const(v1)) { + if (!scf_variable_const(v0) || !scf_variable_const(v1)) return 0; - } assert(v0->type == v1->type); @@ -731,6 +734,12 @@ int scf_expr_calculate(scf_ast_t* ast, scf_expr_t* e, scf_variable_t** pret) if (ret < 0) return ret; + if (SCF_OP_EXPR == node->type) { + node = node->nodes[0]; + + assert(SCF_OP_EXPR != node->type); + } + v = _scf_operand_get(node); if (pret) -- 2.25.1