use 'while loop' instead of 'recursive call' for macro
authoryu.dongliang <18588496441@163.com>
Fri, 27 Sep 2024 09:27:26 +0000 (17:27 +0800)
committeryu.dongliang <18588496441@163.com>
Fri, 27 Sep 2024 09:27:43 +0000 (17:27 +0800)
lex/scf_lex.c
util/scf_def.h

index 87eff60a43d2d5bade86ff4602c4ce06fef01261..7b34b47af742bb373331ace6734ee240938f88db 100644 (file)
@@ -1054,18 +1054,13 @@ static int __parse_macro_argv(scf_lex_t* lex, scf_macro_t* m)
        return 0;
 }
 
-static int __parse_macro_define(scf_lex_t* lex, scf_lex_word_t* w0, scf_lex_word_t* w1)
+static int __parse_macro_define(scf_lex_t* lex)
 {
        scf_lex_word_t** pp;
        scf_lex_word_t*  w = NULL;
        scf_macro_t*     m;
        scf_macro_t*     m0;
 
-       scf_lex_word_free(w0);
-       scf_lex_word_free(w1);
-       w0 = NULL;
-       w1 = NULL;
-
        int ret = __lex_pop_word(lex, &w);
        if (ret < 0)
                return ret;
@@ -1157,44 +1152,6 @@ static int __parse_macro_define(scf_lex_t* lex, scf_lex_word_t* w0, scf_lex_word
        return 0;
 }
 
-static int __parse_macro(scf_lex_t* lex, scf_lex_word_t** pword, scf_lex_word_t* w0)
-{
-       scf_lex_word_t* w1 = NULL;
-
-       int ret = __lex_pop_word(lex, &w1);
-       if (ret < 0) {
-               scf_lex_word_free(w0);
-               return ret;
-       }
-
-       switch (w1->type) {
-
-               case SCF_LEX_WORD_KEY_INCLUDE:
-
-                       scf_lex_push_word(lex, w1);
-                       *pword = w0;
-                       return 0;
-
-                       break;
-               case SCF_LEX_WORD_KEY_DEFINE:
-
-                       ret = __parse_macro_define(lex, w0, w1);
-                       if (ret < 0)
-                               return ret;
-                       break;
-
-               default:
-                       scf_loge("unknown macro '%s', file: %s, line: %d\n", w1->text->data, w1->file->data, w1->line);
-
-                       scf_lex_word_free(w0);
-                       scf_lex_word_free(w1);
-                       return -1;
-                       break;
-       };
-
-       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;
@@ -1316,55 +1273,51 @@ static int __convert_str(scf_lex_word_t* h)
        return 0;
 }
 
-static int __use_macro(scf_lex_t* lex, scf_lex_word_t** pword, scf_lex_word_t* w)
+static scf_macro_t* __find_macro(scf_lex_t* lex, 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) {
-               *pword = w;
-               return 0;
-       }
+       if (!lex->macros)
+               return NULL;
 
+       scf_macro_t* m;
        int i;
+
        for (i = lex->macros->size - 1; i >= 0; i--) {
                m  = lex->macros->data[i];
 
                if (!scf_string_cmp(m->w->text, w->text))
-                       break;
+                       return m;
        }
 
-       if (i < 0) {
-               *pword = w;
-               return 0;
-       }
+       return NULL;
+}
+
+static int __use_macro(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use)
+{
+       scf_lex_word_t** pp;
+       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) {
-                       scf_lex_word_free(w);
+               if (!argv)
                        return -ENOMEM;
-               }
 
-               int ret = __fill_macro_argv(lex, m, w, argv);
+               int ret = __fill_macro_argv(lex, m, use, argv);
                if (ret < 0) {
-                       scf_lex_word_free(w);
                        scf_vector_free(argv);
                        return ret;
                }
        }
 
-       scf_lex_word_free(w);
-       w  = NULL;
-
        h  = NULL;
        pp = &h;
 
        int ret  = 0;
        int hash = 0;
+       int i;
 
        for (p = m->text_list; p; p = p->next) {
 
@@ -1373,10 +1326,7 @@ static int __use_macro(scf_lex_t* lex, scf_lex_word_t** pword, scf_lex_word_t* w
                        continue;
                }
 
-               if (SCF_LEX_WORD_HASH2 == p->type) {
-                       hash = 2;
-                       continue;
-               }
+               scf_logd("p: %s, line: %d, hash: %d\n", p->text->data, p->line, hash);
 
                if (m->argv) {
                        assert(argv);
@@ -1452,8 +1402,81 @@ error:
 #endif
        *pp            = lex->word_list;
        lex->word_list = h;
+       return 0;
+}
+
+static int __use_hash2(scf_lex_t* lex, scf_lex_word_t* prev)
+{
+       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;
+       };
 
-       return scf_lex_pop_word(lex, pword);
+       scf_lex_word_free(after);
+       return ret;
+}
+
+int __lex_use_macro(scf_lex_t* lex, scf_lex_word_t** pp)
+{
+       scf_lex_word_t* w1 = NULL;
+       scf_lex_word_t* w  = *pp;
+       scf_macro_t*    m;
+
+       *pp = NULL;
+
+       while (SCF_LEX_WORD_ID == w->type) {
+
+               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;
+                       continue;
+               }
+
+               int ret = __lex_pop_word(lex, &w1);
+               if (ret < 0) {
+                       scf_lex_word_free(w);
+                       return ret;
+               }
+
+               if (SCF_LEX_WORD_HASH2 != w1->type) {
+                       scf_lex_push_word(lex, w1);
+                       break;
+               }
+
+               scf_lex_word_free(w1);
+               w1 = NULL;
+
+               ret = __use_hash2(lex, w);
+               if (ret < 0) {
+                       scf_lex_word_free(w);
+                       return ret;
+               }
+       }
+
+       *pp = w;
+       return 0;
 }
 
 int scf_lex_pop_word(scf_lex_t* lex, scf_lex_word_t** pword)
@@ -1461,18 +1484,56 @@ int scf_lex_pop_word(scf_lex_t* lex, scf_lex_word_t** pword)
        if (!lex || !lex->fp || !pword)
                return -EINVAL;
 
-       scf_lex_word_t* w = NULL;
+       scf_lex_word_t* w  = NULL;
+       scf_lex_word_t* w1 = NULL;
 
        int ret = __lex_pop_word(lex, &w);
        if (ret < 0)
                return ret;
 
-       if (SCF_LEX_WORD_HASH == w->type)
-               return __parse_macro(lex, pword, w);
+       // parse macro
+       while (SCF_LEX_WORD_HASH == w->type) {
+
+               ret = __lex_pop_word(lex, &w1);
+               if (ret < 0) {
+                       scf_lex_word_free(w);
+                       return ret;
+               }
+
+               switch (w1->type) {
+                       case SCF_LEX_WORD_KEY_INCLUDE:
+
+                               scf_lex_push_word(lex, w1);
+                               *pword = w;
+                               return 0;
+                               break;
+
+                       case SCF_LEX_WORD_KEY_DEFINE:
+                               ret = __parse_macro_define(lex);
+                               break;
+                       default:
+                               scf_loge("unknown macro '%s', file: %s, line: %d\n", w1->text->data, w1->file->data, w1->line);
+                               ret = -1;
+                               break;
+               };
 
-       //use macro to identity
-       if (scf_lex_is_identity(w))
-               return __use_macro(lex, pword, w);
+               scf_lex_word_free(w);
+               scf_lex_word_free(w1);
+               w  = NULL;
+               w1 = NULL;
+
+               if (ret < 0)
+                       return ret;
+
+               ret = __lex_pop_word(lex, &w);
+               if (ret < 0)
+                       return ret;
+       }
+
+       // use macro to pre-process source code
+       ret = __lex_use_macro(lex, &w);
+       if (ret < 0)
+               return ret;
 
        *pword = w;
        return 0;
index 55b1def0cdce3471b7196b3eb26fe0e2d2d573b7..d8dea71ed0ddf0b0620bf662b858b32899d1aa00 100644 (file)
@@ -43,6 +43,8 @@ static inline uint64_t scf_zero_extend(uint64_t src, int src_bits)
        return src;
 }
 
+#define scf_object_of(mp, type, member) ((type*)((char*)mp - offsetof(type, member)))
+
 #define SCF_XCHG(x, y) \
        do {\
                typeof(x) tmp = x; \