From e39af1e0163b8208457b59b0250734b20652898a Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Thu, 26 Sep 2024 23:18:45 +0800 Subject: [PATCH] support simple macro function, like A(x) --> #x --> x --- examples/macro_str.c | 9 ++ lex/scf_lex.c | 229 +++++++++++++++++++++++++++++++++++++++++-- lex/scf_lex_test.c | 8 +- lex/scf_lex_util.c | 3 +- parse/scf_dfa.c | 2 +- 5 files changed, 237 insertions(+), 14 deletions(-) create mode 100644 examples/macro_str.c diff --git a/examples/macro_str.c b/examples/macro_str.c new file mode 100644 index 0000000..354799b --- /dev/null +++ b/examples/macro_str.c @@ -0,0 +1,9 @@ +#define A(x) #x + +int printf(const char* fmt, ...); + +int main() +{ + printf("%s\n", A(zzz)); + return 0; +} diff --git a/lex/scf_lex.c b/lex/scf_lex.c index 42fff04..87eff60 100644 --- a/lex/scf_lex.c +++ b/lex/scf_lex.c @@ -1038,6 +1038,8 @@ static int __parse_macro_argv(scf_lex_t* lex, scf_macro_t* m) } } + scf_logw("macro '%s' arg: %s\n", m->w->text->data, w->text->data); + ret = scf_vector_add(m->argv, w); if (ret < 0) { scf_lex_word_free(w); @@ -1193,11 +1195,133 @@ static int __parse_macro(scf_lex_t* lex, scf_lex_word_t** pword, scf_lex_word_t* return scf_lex_pop_word(lex, pword); } +static int __fill_macro_argv(scf_lex_t* lex, 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); + if (ret < 0) + return ret; + + if (SCF_LEX_WORD_LP != w->type) { + scf_loge("macro '%s' needs args, file: %s, line: %d\n", m->w->text->data, w->file->data, w->line); + scf_lex_word_free(w); + return -1; + } + + scf_lex_word_free(w); + w = NULL; + + int n_lps = 0; + int n_rps = 0; + int i; + + pp = NULL; + + while (1) { + ret = __lex_pop_word(lex, &w); + if (ret < 0) + return ret; + + if (SCF_LEX_WORD_COMMA == w->type) { + if (!pp) { + 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; + } + + scf_lex_word_free(w); + w = NULL; + + if (n_rps == n_lps) + pp = NULL; + continue; + + } else if (SCF_LEX_WORD_LP == w->type) + n_lps++; + else if (SCF_LEX_WORD_RP == w->type) { + n_rps++; + + if (n_rps > n_lps) { + scf_lex_word_free(w); + w = NULL; + break; + } + } + + w->next = NULL; + + if (pp) + *pp = w; + else { + ret = scf_vector_add(argv, w); + if (ret < 0) { + scf_lex_word_free(w); + goto error; + } + } + + pp = &w->next; + w = NULL; + } + + if (m->argv->size != argv->size) { + 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); + } + + argv->size = 0; + return ret; +} + +static int __convert_str(scf_lex_word_t* h) +{ + scf_lex_word_t* w; + scf_string_t* s; + + if (h->type != SCF_LEX_WORD_CONST_STRING) { + h->type = SCF_LEX_WORD_CONST_STRING; + + h->data.s = scf_string_clone(h->text); + if (!h->data.s) + return -ENOMEM; + } + + for (w = h->next; w; w = w->next) { + + if (SCF_LEX_WORD_CONST_STRING != w->type) + s = w->text; + else + s = w->data.s; + + int ret = scf_string_cat(h->data.s, s); + if (ret < 0) + return ret; + } + + scf_logw("h: %s, file: %s, line: %d\n", h->data.s->data, h->file->data, h->line); + return 0; +} + static int __use_macro(scf_lex_t* lex, scf_lex_word_t** pword, scf_lex_word_t* w) { scf_lex_word_t** pp; scf_lex_word_t* p; scf_lex_word_t* h; + scf_vector_t* argv = NULL; scf_macro_t* m; if (!lex->macros) { @@ -1218,23 +1342,114 @@ static int __use_macro(scf_lex_t* lex, scf_lex_word_t** pword, scf_lex_word_t* w return 0; } + if (m->argv) { + argv = scf_vector_alloc(); + if (!argv) { + scf_lex_word_free(w); + return -ENOMEM; + } + + int ret = __fill_macro_argv(lex, m, w, argv); + if (ret < 0) { + scf_lex_word_free(w); + scf_vector_free(argv); + return ret; + } + } + scf_lex_word_free(w); - w = NULL; + w = NULL; h = NULL; pp = &h; + + int ret = 0; + int hash = 0; + for (p = m->text_list; p; p = p->next) { - w = scf_lex_word_clone(p); - if (!w) { - scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free); - return -ENOMEM; + if (SCF_LEX_WORD_HASH == p->type) { + hash = 1; + continue; } - *pp = w; - pp = &w->next; + if (SCF_LEX_WORD_HASH2 == p->type) { + hash = 2; + continue; + } + + if (m->argv) { + assert(argv); + assert(argv->size >= m->argv->size); + + for (i = 0; i < m->argv->size; i++) { + w = m->argv->data[i]; + + if (!scf_string_cmp(w->text, p->text)) + break; + } + + if (i < m->argv->size) { + w = argv->data[i]; + + if (1 == hash) { + ret = __convert_str(w); + if (ret < 0) + goto error; + + scf_slist_clear(w->next, scf_lex_word_t, next, scf_lex_word_free); + w->next = NULL; + } + + *pp = w; + while (w) { + pp = &w->next; + w = w->next; + } + + argv->data[i] = NULL; + + hash = 0; + continue; + } + } + + *pp = scf_lex_word_clone(p); + if (!*pp) { + ret = -ENOMEM; + goto error; + } + + pp = &(*pp)->next; + + hash = 0; + } + +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); + return ret; + } + +#if 0 + w = h; + while (w) { + scf_logi("---------- %s, line: %d\n", w->text->data, w->line); + w = w->next; + } +#endif *pp = lex->word_list; lex->word_list = h; diff --git a/lex/scf_lex_test.c b/lex/scf_lex_test.c index 7b1d55d..8f94494 100644 --- a/lex/scf_lex_test.c +++ b/lex/scf_lex_test.c @@ -5,14 +5,14 @@ int main(int argc, char* argv[]) scf_lex_t* lex = NULL; if (scf_lex_open(&lex, argv[1]) < 0) { - printf("%s(),%d, error: \n", __func__, __LINE__); + scf_loge("\n"); return -1; } scf_lex_word_t* w = NULL; while (1) { if (scf_lex_pop_word(lex, &w) < 0) { - printf("%s(),%d, error: \n", __func__, __LINE__); + scf_loge("\n"); return -1; } @@ -31,7 +31,7 @@ int main(int argc, char* argv[]) printf("\n"); if (SCF_LEX_WORD_EOF == w->type) { - printf("%s(),%d, eof\n", __func__, __LINE__); + scf_logi("eof\n"); break; } @@ -39,6 +39,6 @@ int main(int argc, char* argv[]) w = NULL; } - printf("%s(),%d, main ok\n", __func__, __LINE__); + scf_logi("main ok\n"); return 0; } diff --git a/lex/scf_lex_util.c b/lex/scf_lex_util.c index 5a6e589..edc2ede 100644 --- a/lex/scf_lex_util.c +++ b/lex/scf_lex_util.c @@ -13,10 +13,9 @@ scf_char_t* _lex_pop_char(scf_lex_t* lex) return c; } - c = malloc(sizeof(scf_char_t)); + c = calloc(1, sizeof(scf_char_t)); if (!c) return NULL; - c->next = NULL; int ret = fgetc(lex->fp); if (EOF == ret) { diff --git a/parse/scf_dfa.c b/parse/scf_dfa.c index 2c14d16..e9cbba6 100644 --- a/parse/scf_dfa.c +++ b/parse/scf_dfa.c @@ -399,7 +399,7 @@ static int _scf_dfa_node_parse_word(scf_dfa_t* dfa, scf_dfa_node_t* node, scf_ve scf_logd("pop w->type: %d, '%s', line: %d, pos: %d\n", w->type, w->text->data, w->line, w->pos); } else if (SCF_DFA_OK == ret) { - scf_logi("SCF_DFA_OK\n"); + scf_logi("SCF_DFA_OK\n\n"); return SCF_DFA_OK; } else if (SCF_DFA_CONTINUE == ret) { -- 2.25.1