1, support macro: __VA_ARGS__, #error, support 'defined' with () in #if, master
authoryu.dongliang <18588496441@163.com>
Sat, 1 Aug 2026 08:09:54 +0000 (16:09 +0800)
committeryu.dongliang <18588496441@163.com>
Sat, 1 Aug 2026 08:11:46 +0000 (16:11 +0800)
2, ingnore macro: #pragma, #line,
3, add some 'lex check' for wrong source code.

12 files changed:
core/scf_lex_word.h
examples/macro_defined.c [new file with mode: 0644]
examples/macro_error.c [new file with mode: 0644]
examples/macro_if.c
examples/macro_str.c
examples/macro_varg.c [new file with mode: 0644]
lex/scf_lex.c
lex/scf_lex.h
lex/scf_lex_util.c
lex/scf_macro.c
lex/scf_macro_expr.c
parse/scf_dfa_util.h

index 71f0edc89ccaf5fd56e4a18e9ee8bef6110656f7..fae6d83066da709f0b16982d4c60437101f84fc1 100644 (file)
@@ -75,7 +75,7 @@ enum scf_lex_words
        SCF_LEX_N_OPS, // number of operators
 
        SCF_LEX_WORD_RANGE,         // ..  range
-       SCF_LEX_WORD_VAR_ARGS,      // ... variable args
+       SCF_LEX_WORD_VA_ARGS,       // ... variable args
 
        SCF_LEX_WORD_LB,            // { left brace
        SCF_LEX_WORD_RB,            // } right brace
@@ -113,10 +113,15 @@ enum scf_lex_words
        SCF_LEX_WORD_KEY_OPERATOR,  // operator
        SCF_LEX_WORD_KEY_UNDERLINE, // _ underline
 
+       // macro key word
        SCF_LEX_WORD_KEY_INCLUDE,   // #include
        SCF_LEX_WORD_KEY_DEFINE,    // #define
        SCF_LEX_WORD_KEY_UNDEF,     // #undef
 
+       SCF_LEX_WORD_KEY_ERROR,     // #error
+       SCF_LEX_WORD_KEY_LINE,      // #line
+       SCF_LEX_WORD_KEY_PRAGMA,    // #pragma
+
        SCF_LEX_WORD_KEY_IFDEF,     // #ifdef
        SCF_LEX_WORD_KEY_IFNDEF,    // #ifndef
        SCF_LEX_WORD_KEY_ELIF,      // #elif
@@ -216,6 +221,7 @@ struct scf_macro_s
        int              refs;
 
        uint8_t          def_flag:1;
+       uint8_t          vargs_flag:1;
 
        scf_lex_word_t*  w;
        scf_vector_t*    argv;
diff --git a/examples/macro_defined.c b/examples/macro_defined.c
new file mode 100644 (file)
index 0000000..5739bc3
--- /dev/null
@@ -0,0 +1,13 @@
+#define A
+
+#if defined(A)
+int printf(const char* fmt, ...);
+#endif
+
+int main()
+{
+       int define = 5;
+
+       printf("define: %d\n", define);
+       return 0;
+}
diff --git a/examples/macro_error.c b/examples/macro_error.c
new file mode 100644 (file)
index 0000000..190ba69
--- /dev/null
@@ -0,0 +1,15 @@
+#pragma A
+
+#define P
+
+#ifdef P
+int printf(const char* fmt, ...);
+#else
+#error "printf() NOT include!"
+#endif
+
+int main()
+{
+       printf("macro '#error' test ok\n");
+       return 0;
+}
index d3bd4972729c03c75df5d52a96d68dfc659b3363..90ec3e3e047225eb409389bcab916ac221bc5e10 100644 (file)
@@ -1,4 +1,4 @@
-#if 1 ? 2 < 3 ? 0 : 4 : 5
+#if 1 ? 3 < 3 ? 0 : 4 : 5
 int printf(const char* fmt, ...);
 #else
 #endif
index 354799ba4806be98cbdc478bc78b928844117d15..cbf19f8477bb69fcd040dc8716a2ab030e92666d 100644 (file)
@@ -1,9 +1,9 @@
-#define A(x) #x
+#define A(x, y) #x, (y)
 
 int printf(const char* fmt, ...);
 
 int main()
 {
-       printf("%s\n", A(zzz));
+       printf("%s, %d\n", A(zzz, 1));
        return 0;
 }
diff --git a/examples/macro_varg.c b/examples/macro_varg.c
new file mode 100644 (file)
index 0000000..b81c59a
--- /dev/null
@@ -0,0 +1,9 @@
+int printf(const char* fmt, ...);
+
+#define logi(fmt, ...) printf("%s(), %d, info: "fmt, __func__, __LINE__, ##__VA_ARGS__)
+
+int main()
+{
+       logi("hello, %d, %lg\n", 1, 3.14);
+       return 0;
+}
index 998adfb9a6dd5dcb22dad5e7633baec060a99ebe..c2c69c1e7f3745f6949d589256e9c1c675e8def5 100644 (file)
@@ -1,20 +1,30 @@
 #include"scf_lex.h"
 
-static scf_key_word_t  key_words[] =
+static scf_key_word_t  macro_key_words[] =
 {
-       {SCF_CSTR("if"),        SCF_LEX_WORD_KEY_IF},
-       {SCF_CSTR("else"),      SCF_LEX_WORD_KEY_ELSE},
-
        {SCF_CSTR("include"),   SCF_LEX_WORD_KEY_INCLUDE},
        {SCF_CSTR("define"),    SCF_LEX_WORD_KEY_DEFINE},
-       {SCF_CSTR("defined"),   SCF_LEX_WORD_KEY_DEFINED},
-       {SCF_CSTR("undef"),     SCF_LEX_WORD_KEY_UNDEF},
 
-       {SCF_CSTR("ifdef"),     SCF_LEX_WORD_KEY_IFDEF},
        {SCF_CSTR("ifndef"),    SCF_LEX_WORD_KEY_IFNDEF},
+       {SCF_CSTR("ifdef"),     SCF_LEX_WORD_KEY_IFDEF},
+
+       {SCF_CSTR("if"),        SCF_LEX_WORD_KEY_IF},
+       {SCF_CSTR("else"),      SCF_LEX_WORD_KEY_ELSE},
        {SCF_CSTR("elif"),      SCF_LEX_WORD_KEY_ELIF},
        {SCF_CSTR("endif"),     SCF_LEX_WORD_KEY_ENDIF},
 
+       {SCF_CSTR("undef"),     SCF_LEX_WORD_KEY_UNDEF},
+
+       {SCF_CSTR("pragma"),    SCF_LEX_WORD_KEY_PRAGMA},
+       {SCF_CSTR("line"),      SCF_LEX_WORD_KEY_LINE},
+       {SCF_CSTR("error"),     SCF_LEX_WORD_KEY_ERROR},
+};
+
+static scf_key_word_t  key_words[] =
+{
+       {SCF_CSTR("if"),        SCF_LEX_WORD_KEY_IF},
+       {SCF_CSTR("else"),      SCF_LEX_WORD_KEY_ELSE},
+
        {SCF_CSTR("for"),       SCF_LEX_WORD_KEY_FOR},
        {SCF_CSTR("while"),     SCF_LEX_WORD_KEY_WHILE},
        {SCF_CSTR("do"),        SCF_LEX_WORD_KEY_DO},
@@ -110,13 +120,13 @@ static scf_escape_char_t  escape_chars[] =
        {'0', '\0'},
 };
 
-int _find_key_word(const scf_string_t* text)
+static int __find_key_word(const scf_string_t* text, const scf_key_word_t* key_words, int n)
 {
-       scf_key_word_t* key;
+       const scf_key_word_t* key;
        int i;
 
-       for (i  = 0; i < sizeof(key_words) / sizeof(key_words[0]); i++) {
-               key =              &key_words[i];
+       for (i  = 0; i < n; i++) {
+               key = &key_words[i];
 
                if (text->len == key->len && !memcmp(text->data, key->text, key->len))
                        return key->type;
@@ -125,6 +135,16 @@ int _find_key_word(const scf_string_t* text)
        return -1;
 }
 
+int _find_key_word(const scf_string_t* text)
+{
+       return __find_key_word(text, key_words, sizeof(key_words) / sizeof(key_words[0]));
+}
+
+static int _find_macro_key_word(const scf_string_t* text)
+{
+       return __find_key_word(text, macro_key_words, sizeof(macro_key_words) / sizeof(macro_key_words[0]));
+}
+
 static int _find_escape_char(const int c)
 {
        int i;
@@ -583,7 +603,7 @@ static int _lex_string(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0)
        }
 }
 
-static int _lex_macro(scf_lex_t* lex)
+static int _lex_macro_LF(scf_lex_t* lex)
 {
        scf_char_t*  h  =  NULL;
        scf_char_t** pp = &h;
@@ -914,20 +934,47 @@ int __lex_pop_word(scf_lex_t* lex, scf_lex_word_t** pword)
 
                if ('#' == c->c) {
                        w->type = SCF_LEX_WORD_HASH2;
-                       w->text = scf_string_cstr("##");
+                       w->text = scf_string_cstr_len("##", 2);
 
                        lex->pos += 2;
                        free(c);
                } else {
-                       w->text = scf_string_cstr("#");
+                       w->text = scf_string_cstr_len("#", 1);
 
                        lex->pos++;
                        _lex_push_char(lex, c);
                }
 
                c = NULL;
+
+               int ret = _lex_macro_LF(lex);
+               if (ret < 0) {
+                       scf_lex_word_free(w);
+                       return ret;
+               }
+
+               if (SCF_LEX_WORD_HASH == w->type) {
+                       scf_lex_word_t* key = NULL;
+
+                       ret = __lex_pop_word(lex, &key);
+                       if (ret < 0) {
+                               scf_lex_word_free(w);
+                               return ret;
+                       }
+
+                       if (SCF_LEX_WORD_ID == key->type) {
+
+                               int type = _find_macro_key_word(key->text);
+                               if (type >= 0)
+                                       key->type = type;
+                       }
+
+                       scf_lex_push_word(lex, key);
+                       key = NULL;
+               }
+
                *pword = w;
-               return _lex_macro(lex);
+               return 0;
        }
 
        if ('$' == c->c && lex->asm_flag)
@@ -1021,6 +1068,17 @@ int scf_lex_pop_word(scf_lex_t* lex, scf_lex_word_t** pword)
                                ret = __parse_macro_define(lex, 0);
                                break;
 
+                       case SCF_LEX_WORD_KEY_PRAGMA:
+                       case SCF_LEX_WORD_KEY_LINE:
+                               ret = __macro_drop_to_LF(lex);
+                               break;
+
+                       case SCF_LEX_WORD_KEY_ERROR:
+                               scf_loge("#error ");
+                               __macro_print_to_LF(lex);
+                               ret = -EINVAL;
+                               break;
+
                        default:
                                if (lex->asm_flag) {
                                        scf_lex_push_word(lex, w1);
index a5c15f91b2c177908ce5241bafc48828ed5493e7..79b93914c0412a5aa5e3304e7441759dea072d8a 100644 (file)
@@ -53,6 +53,7 @@ struct scf_lex_s
        uint8_t         asm_flag:1;
 };
 
+int _find_key_word(const scf_string_t* text);
 
 scf_char_t*  _lex_pop_char (scf_lex_t* lex);
 void         _lex_push_char(scf_lex_t* lex, scf_char_t* c);
@@ -70,7 +71,9 @@ int    __macro_if_expr(scf_lex_t* lex);
 
 int    __macro_pop_to (scf_lex_t* lex, scf_lex_word_t** h,   scf_lex_word_t** pw1, scf_lex_word_t** pw2);
 int    __macro_drop_to(scf_lex_t* lex, scf_lex_word_t** pw1, scf_lex_word_t** pw2);
-int    __macro_drop_to_LF(scf_lex_t* lex);
+
+int    __macro_drop_to_LF (scf_lex_t* lex);
+int    __macro_print_to_LF(scf_lex_t* lex);
 
 int    __parse_macro_define(scf_lex_t* lex, int def_flag);
 int    __parse_macro_ifdef (scf_lex_t* lex, int def_flag);
index 5de3bd4d448d4d8c5f249c369f8a8914b0908ea3..a6360e2ff1a7b07ef4a12eaf67c11a5684d7cdff 100644 (file)
@@ -1,7 +1,5 @@
 #include"scf_lex.h"
 
-int _find_key_word(const char* text);
-
 static scf_key_word_t  number_postfix[] =
 {
        {SCF_CSTR("l"),   SCF_LEX_WORD_CONST_INT},
@@ -721,7 +719,7 @@ 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_VAR_ARGS);
+                       w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_VA_ARGS);
                        w->text = s;
                        s = NULL;
                } else {
@@ -752,7 +750,7 @@ int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0)
                _lex_push_char(lex, c1);
                c1 = NULL;
 
-               int type = _find_key_word(s->data);
+               int type = _find_key_word(s);
                if (type < 0) {
                        scf_loge("unknown asm key word '%s', file: %s, line: %d\n", s->data, lex->file->data, lex->nb_lines);
 
index 8afdd567fc5c41e717c0387ab5436faf6c8dc41f..b4c8f3debc4ce92197bae33daec8465f576ac067 100644 (file)
@@ -18,6 +18,35 @@ scf_macro_t* __find_macro(scf_lex_t* lex, scf_lex_word_t* w)
        return NULL;
 }
 
+int __macro_print_to_LF(scf_lex_t* lex)
+{
+       scf_lex_word_t* w = NULL;
+       int type;
+
+       do {
+               int ret = __lex_pop_word(lex, &w);
+               if (ret < 0)
+                       return ret;
+
+               type = w->type;
+
+               if (SCF_LEX_WORD_LF != type) {
+
+                       printf("%s ", w->text->data);
+               }
+
+               scf_lex_word_free(w);
+               w = NULL;
+
+               if (SCF_LEX_WORD_EOF == type)
+                       return -EINVAL;
+
+       } while (SCF_LEX_WORD_LF != type);
+
+       printf("\n");
+       return 0;
+}
+
 int __macro_drop_to_LF(scf_lex_t* lex)
 {
        scf_lex_word_t* w = NULL;
@@ -198,7 +227,8 @@ static int __parse_macro_argv(scf_lex_t* lex, scf_macro_t* m)
                        }
                }
 
-               if (!scf_lex_is_identity(w)) {
+               if (SCF_LEX_WORD_ID != w->type && SCF_LEX_WORD_VA_ARGS != w->type) {
+
                        scf_loge("macro arg '%s' should be an identity, file: %s, line: %d\n", w->text->data, w->file->data, w->line);
                        scf_lex_word_free(w);
                        return -EINVAL;
@@ -223,10 +253,21 @@ 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) {
+               if (m->vargs_flag) {
+                       scf_loge("macro has arg '%s' after '...' which must be the last arg, file: %s, line: %d\n", w->text->data, w->file->data, w->line);
                        scf_lex_word_free(w);
-                       return ret;
+                       return -EINVAL;
+               }
+
+               if (SCF_LEX_WORD_VA_ARGS == w->type) {
+                       m->vargs_flag = 1;
+                       scf_lex_word_free(w);
+               } else {
+                       ret = scf_vector_add(m->argv, w);
+                       if (ret < 0) {
+                               scf_lex_word_free(w);
+                               return ret;
+                       }
                }
                w = NULL;
 
@@ -485,8 +526,10 @@ static int __fill_macro_argv(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use
                                goto error;
                        }
 
-                       scf_lex_word_free(w);
-                       w  = NULL;
+                       w->next = NULL;
+
+                       *pp = w;
+                       pp = &w->next;
 
                        if (n_rps == n_lps)
                                pp = NULL;
@@ -520,7 +563,9 @@ static int __fill_macro_argv(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use
                w  = NULL;
        }
 
-       if (m->argv->size != argv->size) {
+       if (m->argv->size > argv->size
+                       || (m->argv->size < argv->size && !m->vargs_flag)) {
+
                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;
@@ -544,6 +589,9 @@ static int __convert_str(scf_lex_word_t* h)
        scf_lex_word_t* w;
        scf_string_t*   s;
 
+       if (SCF_LEX_WORD_COMMA == h->type && !h->next)
+               return 0;
+
        if (h->type != SCF_LEX_WORD_CONST_STRING) {
                h->type  = SCF_LEX_WORD_CONST_STRING;
 
@@ -555,6 +603,9 @@ static int __convert_str(scf_lex_word_t* h)
        while ( h->next) {
                w = h->next;
 
+               if (SCF_LEX_WORD_COMMA == w->type && !w->next)
+                       break;
+
                if (SCF_LEX_WORD_CONST_STRING != w->type)
                        s = w->text;
                else
@@ -613,7 +664,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, hash: %d\n", p->text->data, p->line, hash);
+               scf_logd("p: '%s', line: %d:%d, hash: %d\n", p->text->data, p->line, p->pos, hash);
 
                if (m->argv) {
                        assert(argv);
@@ -626,22 +677,43 @@ static int __use_macro(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use)
                                        break;
                        }
 
+                       int j = 0;
+                       int n = 0;
+
                        if (i < m->argv->size) {
+                               j = i;
+                               n = i + 1;
+
+                       } else if (m->vargs_flag && !strcmp(p->text->data, "__VA_ARGS__")) {
+                               j = i;
+                               n = argv->size;
+                       }
+
+                       if (j < n) {
                                scf_lex_word_t** tmp = pp;
 
-                               for (w = argv->data[i]; w; w = w->next) {
+                               do {
+                                       for (w = argv->data[j]; w; w = w->next) {
 
-                                       *pp = scf_lex_word_clone(w);
-                                       if (!*pp) {
-                                               ret = -ENOMEM;
-                                               goto error;
-                                       }
+                                               if (j < m->argv->size
+                                                               && SCF_LEX_WORD_COMMA == w->type
+                                                               && !w->next)
+                                                       break;
 
-                                       if (!strcmp((*pp)->text->data, "__LINE__"))
-                                               (*pp)->data.u64 = use->line;
+                                               *pp = scf_lex_word_clone(w);
+                                               if (!*pp) {
+                                                       ret = -ENOMEM;
+                                                       goto error;
+                                               }
 
-                                       pp = &(*pp)->next;
-                               }
+                                               if (!strcmp((*pp)->text->data, "__LINE__"))
+                                                       (*pp)->data.u64 = use->line;
+
+                                               scf_logd("\033[32m p: '%s', line: %d:%d, hash: %d\033[0m\n", (*pp)->text->data, (*pp)->line, (*pp)->pos, hash);
+
+                                               pp = &(*pp)->next;
+                                       }
+                               } while (++j < n);
 
                                if (1 == hash) {
                                        ret = __convert_str(*tmp);
@@ -688,6 +760,56 @@ error:
                return ret;
        }
 
+       w = h;
+       while (w) {
+               scf_lex_word_t* w2;
+               scf_lex_word_t* w1 = w->next;
+
+               if (!w1)
+                       break;
+
+               if (SCF_LEX_WORD_CONST_STRING == w1->type) {
+
+                       if (SCF_LEX_WORD_CONST_STRING == w->type) {
+
+                               if ((ret = scf_string_cat(w->text, w1->text)) < 0
+                                || (ret = scf_string_cat(w->data.s, w1->data.s)) < 0) {
+
+                                       scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free);
+                                       return ret;
+                               }
+
+                               w->next = w1->next;
+
+                               scf_lex_word_free(w1);
+                               w1 = NULL;
+                               continue;
+                       }
+
+               } else if (SCF_LEX_WORD_COMMA == w1->type) {
+                       w2 = w1->next;
+
+                       if (w2 && SCF_LEX_WORD_HASH2 == w2->type) {
+                               w1->next = w2->next;
+
+                               scf_lex_word_free(w2);
+                               w2 = w1->next;
+
+                               if (w2 && SCF_LEX_WORD_ID == w2->type && !strcmp(w2->text->data, "__VA_ARGS__")) {
+
+                                       w->next = w2->next;
+
+                                       scf_lex_word_free(w1);
+                                       scf_lex_word_free(w2);
+                                       w1 = NULL;
+                                       w2 = NULL;
+                               }
+                       }
+               }
+
+               w = w->next;
+       }
+
 #if 0
        w = h;
        while (w) {
@@ -695,6 +817,7 @@ error:
                w = w->next;
        }
 #endif
+
        *pp            = lex->word_list;
        lex->word_list = h;
        return 0;
index e5ae60d80fc07cfef66d57b7f01e13ddc8867fba..6602c9379b225e42e04e037df212c6449ddb464e 100644 (file)
@@ -56,6 +56,9 @@ static int __macro_unary_operand(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_w
        if (ret < 0)
                return ret;
 
+       if (SCF_LEX_WORD_ID == w0->type && !strcmp(w0->text->data, "defined"))
+               w0->type = SCF_LEX_WORD_KEY_DEFINED;
+
        switch (w0->type)
        {
                case SCF_LEX_WORD_PLUS:
@@ -108,6 +111,8 @@ static int __macro_binary_operand(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_
 
                *ctx->pp = op2;
                ctx->pp = &op2->next;
+
+               ctx->n_rps++;
                return 0;
        }
 
@@ -180,19 +185,36 @@ MACRO_OPERATOR_BINARY(logic_or,  ||)
 static int __macro_operator_defined(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand)
 {
        scf_lex_word_t* w0 = NULL;
+       int ret;
 
-       int ret = __lex_pop_word(lex, &w0);
-       if (ret < 0)
-               return ret;
+       int n_lps = 0;
+       int n_rps = 0;
+
+       while (1) {
+               ret = __lex_pop_word(lex, &w0);
+               if (ret < 0)
+                       return ret;
+
+               w0->next = NULL;
+               *ctx->pp = w0;
+               ctx->pp = &w0->next;
 
-       if (SCF_LEX_WORD_ID != w0->type) {
-               scf_loge("'%s' after 'defined' in #if is NOT an macro identity, file: %s, line: %d\n",
-                               w0->text->data, w0->file->data, w0->line);
+               if (SCF_LEX_WORD_ID == w0->type)
+                       break;
+
+               if (SCF_LEX_WORD_LP != w0->type) {
+
+                       scf_loge("'%s' after 'defined' in #if is NOT an macro identity, file: %s, line: %d\n",
+                                       w0->text->data, w0->file->data, w0->line);
+                       return -EINVAL;
+               }
 
-               ret = -EINVAL;
-               goto error;
+               n_lps++;
+               w0 = NULL;
        }
 
+       assert(SCF_LEX_WORD_ID == w0->type);
+
        if (__find_macro(lex, w0))
                w0->data.i64 = 1;
        else
@@ -203,13 +225,30 @@ static int __macro_operator_defined(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_le
 
        scf_logi("w0: %s, result: %ld\n", w0->text->data, w0->data.i64);
 
-       ret = 0;
+       w0 = NULL;
 
-error:
-       w0->next = NULL;
-       *ctx->pp = w0;
-       ctx->pp = &w0->next;
-       return ret;
+       while (n_rps < n_lps) {
+
+               ret = __lex_pop_word(lex, &w0);
+               if (ret < 0)
+                       return ret;
+
+               w0->next = NULL;
+               *ctx->pp = w0;
+               ctx->pp = &w0->next;
+
+               if (SCF_LEX_WORD_RP != w0->type) {
+
+                       scf_loge("too less ')' before '%s' in #if, file: %s, line: %d\n",
+                                       w0->text->data, w0->file->data, w0->line);
+                       return -EINVAL;
+               }
+
+               n_rps++;
+               w0 = NULL;
+       }
+
+       return 0;
 }
 
 #define MACRO_OPERATOR_UNARY(name, op) \
@@ -362,6 +401,13 @@ static int __macro_operator_lp(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_wor
 
 static int __macro_operator_rp(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand)
 {
+       if (++ctx->n_rps > ctx->n_lps) {
+
+               scf_loge("too many '%s', file: %s, line: %d, pos: %d\n",
+                               w_op->text->data, w_op->file->data, w_op->line, w_op->pos);
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -431,11 +477,14 @@ static int __macro_operator_lp(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_wor
        *ctx->pp = op2;
        ctx->pp = &op2->next;
 
+       ctx->n_lps++;
+
        scf_macro_operator_pt  f;
 
        switch (op2->type)
        {
                case SCF_LEX_WORD_RP:
+                       ctx->n_rps++;
                        break;
 
                case SCF_LEX_WORD_STAR:
@@ -496,6 +545,9 @@ static int __macro_expr(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w,
                return -EINVAL;
        }
 
+       if (SCF_LEX_WORD_ID == w->type && !strcmp(w->text->data, "defined"))
+               w->type = SCF_LEX_WORD_KEY_DEFINED;
+
        if (scf_lex_is_operator(w)) {
 
                w->next = NULL;
@@ -555,6 +607,9 @@ int __macro_if_expr(scf_lex_t* lex)
                        goto error;
                }
 
+               if (SCF_LEX_WORD_ID == w->type && !strcmp(w->text->data, "defined"))
+                       w->type = SCF_LEX_WORD_KEY_DEFINED;
+
                if (scf_lex_is_operator(w)) {
                        scf_macro_operator_pt f = macro_operators[w->type];
                        if (!f) {
@@ -595,6 +650,14 @@ int __macro_if_expr(scf_lex_t* lex)
                        goto error;
                }
 
+               if (operand) {
+                       scf_loge("NO binary operator before operand '%s', file: %s, line: %d\n",
+                                       w->text->data, w->file->data, w->line);
+
+                       ret = -EINVAL;
+                       goto error;
+               }
+
                scf_logi("w: %s, w->data.u64: %ld\n", w->text->data, w->data.u64);
 
                operand = w;
index ece42609c3eebdec9953545fbbec2e15e797543a..b38ea2e0330485440eacf4846e2363304b1a47ca 100644 (file)
@@ -183,7 +183,7 @@ static inline int scf_dfa_is_vargs(scf_dfa_t* dfa, void* word)
 {
        scf_lex_word_t* w = word;
 
-       return SCF_LEX_WORD_VAR_ARGS == w->type;
+       return SCF_LEX_WORD_VA_ARGS == w->type;
 }
 
 static inline int scf_dfa_is_const(scf_dfa_t* dfa, void* word)