1, support macro expr in #if,
authoryu.dongliang <18588496441@163.com>
Fri, 3 Jul 2026 03:51:26 +0000 (11:51 +0800)
committeryu.dongliang <18588496441@163.com>
Fri, 3 Jul 2026 03:51:36 +0000 (11:51 +0800)
2, support C style function pointer,
3, support C style union & struct,
4, support trinary operator in #if macro expr.

21 files changed:
core/scf_lex_word.h
examples/c_func_pointer.c [new file with mode: 0644]
examples/macro_if.c [new file with mode: 0644]
examples/union_float_reg.c [new file with mode: 0644]
lex/Makefile
lex/scf_lex.c
lex/scf_lex.h
lex/scf_lex_util.c
lex/scf_macro.c
lex/scf_macro_expr.c [new file with mode: 0644]
native/x64/scf_x64_inst.c
parse/Makefile
parse/scf_dfa_function.c
parse/scf_dfa_macro.c
parse/scf_dfa_util.h
parse/scf_operator_handler_expr.c
parse/scf_operator_handler_semantic.c
parse/scf_parse.c
util/scf_string.c
util/scf_string.h
util/scf_vector.h

index 4a8010c2fb7327b2e5a31d2ff910f981592f2005..15dfb57da1c61fab312ffe9a751a1d27c19c2e86 100644 (file)
@@ -10,26 +10,26 @@ typedef struct scf_macro_s      scf_macro_t;
 
 enum scf_lex_words
 {
-       SCF_LEX_WORD_PLUS = 0,          // +
-       SCF_LEX_WORD_MINUS,                     // -
-       SCF_LEX_WORD_STAR,                      // *
-       SCF_LEX_WORD_DIV,                       // / div
+       SCF_LEX_WORD_PLUS = 0,      // +
+       SCF_LEX_WORD_MINUS,         // -
+       SCF_LEX_WORD_STAR,          // *
+       SCF_LEX_WORD_DIV,           // / div
        SCF_LEX_WORD_MOD,           // %
 
-       SCF_LEX_WORD_INC,                       // ++
-       SCF_LEX_WORD_DEC,                       // --
+       SCF_LEX_WORD_INC,           // ++
+       SCF_LEX_WORD_DEC,           // --
 
        SCF_LEX_WORD_SHL,           // <<
        SCF_LEX_WORD_SHR,           // >>
 
-       SCF_LEX_WORD_BIT_AND,           // &
-       SCF_LEX_WORD_BIT_OR,            // |
-       SCF_LEX_WORD_BIT_NOT,           // ~
+       SCF_LEX_WORD_BIT_AND,       // &
+       SCF_LEX_WORD_BIT_OR,        // |
+       SCF_LEX_WORD_BIT_NOT,       // ~
+       SCF_LEX_WORD_BIT_XOR,       // ^
 
        SCF_LEX_WORD_LOGIC_AND,         // &&
        SCF_LEX_WORD_LOGIC_OR,          // ||
        SCF_LEX_WORD_LOGIC_NOT,         // !
-       SCF_LEX_WORD_LOGIC_XOR,     // xor
 
        SCF_LEX_WORD_ASSIGN,             //  = assign
        SCF_LEX_WORD_ADD_ASSIGN,     // +=
@@ -64,10 +64,16 @@ enum scf_lex_words
        SCF_LEX_WORD_KEY_NEW,       // create class object
        SCF_LEX_WORD_KEY_CONTAINER, // container_of
        SCF_LEX_WORD_KEY_VA_ARG,    // va_arg
+       SCF_LEX_WORD_KEY_DEFINED,   // #defined
+
+       SCF_LEX_WORD_Q_MASK,        // ?
+       SCF_LEX_WORD_COLON,         // : colon
 
        SCF_LEX_WORD_ARROW,         // ->  arrow
        SCF_LEX_WORD_DOT,           // .   dot
 
+       SCF_LEX_N_OPS, // number of operators
+
        SCF_LEX_WORD_RANGE,         // ..  range
        SCF_LEX_WORD_VAR_ARGS,      // ... variable args
 
@@ -81,7 +87,6 @@ enum scf_lex_words
 
        SCF_LEX_WORD_COMMA,         // , comma
        SCF_LEX_WORD_SEMICOLON,     // ;
-       SCF_LEX_WORD_COLON,                     // : colon
        SCF_LEX_WORD_SPACE,                     // ' ' space
 
        // eof
diff --git a/examples/c_func_pointer.c b/examples/c_func_pointer.c
new file mode 100644 (file)
index 0000000..f2bda8b
--- /dev/null
@@ -0,0 +1,11 @@
+int printf(const char* fmt, ...);
+
+int (*pf)(const char* fmt, ...);
+
+int main()
+{
+       pf = printf;
+
+       pf("hello world\n");
+       return 0;
+}
diff --git a/examples/macro_if.c b/examples/macro_if.c
new file mode 100644 (file)
index 0000000..d3bd497
--- /dev/null
@@ -0,0 +1,10 @@
+#if 1 ? 2 < 3 ? 0 : 4 : 5
+int printf(const char* fmt, ...);
+#else
+#endif
+
+int main()
+{
+       printf("hello world\n");
+       return 0;
+}
diff --git a/examples/union_float_reg.c b/examples/union_float_reg.c
new file mode 100644 (file)
index 0000000..e1fe203
--- /dev/null
@@ -0,0 +1,20 @@
+int printf(const char* fmt, ...);
+
+union Reg {
+       uint32_t data;
+
+       struct {
+               uint32_t decimal:23;
+               uint32_t exp :8;
+               uint32_t sign:1;
+       };
+};
+
+int main()
+{
+       Reg r;
+       r.data = 0x3f800000;
+
+       printf("r.decimal: %#x, r.exp: %#x, r.sign: %#x\n", r.decimal, r.exp, r.sign);
+       return 0;
+}
index f6b9436ac2f09af42b650872dc07cd64d4324e12..aa6938e407d0e99b9329046f329fc5ae87bd402c 100644 (file)
@@ -1,8 +1,9 @@
 CFILES += ../util/scf_string.c
+CFILES += ../core/scf_lex_word.c
 CFILES += scf_lex.c
 CFILES += scf_lex_util.c
 CFILES += scf_macro.c
-CFILES += ../core/scf_lex_word.c
+CFILES += scf_macro_expr.c
 CFILES += scf_lex_test.c
 
 CFLAGS += -g 
index 148ec60054c8d669c1ffb5b48bdacd4a5041f734..068b6c6f7dbfa50ea231b4d559cc8443e5991175 100644 (file)
 
 static scf_key_word_t  key_words[] =
 {
-       {"if",        SCF_LEX_WORD_KEY_IF},
-       {"else",      SCF_LEX_WORD_KEY_ELSE},
-
-       {"include",   SCF_LEX_WORD_KEY_INCLUDE},
-       {"define",    SCF_LEX_WORD_KEY_DEFINE},
-       {"undef",     SCF_LEX_WORD_KEY_UNDEF},
-
-       {"ifdef",     SCF_LEX_WORD_KEY_IFDEF},
-       {"ifndef",    SCF_LEX_WORD_KEY_IFNDEF},
-       {"elif",      SCF_LEX_WORD_KEY_ELIF},
-       {"endif",     SCF_LEX_WORD_KEY_ENDIF},
-
-       {"for",       SCF_LEX_WORD_KEY_FOR},
-       {"while",     SCF_LEX_WORD_KEY_WHILE},
-       {"do",        SCF_LEX_WORD_KEY_DO},
-
-       {"break",     SCF_LEX_WORD_KEY_BREAK},
-       {"continue",  SCF_LEX_WORD_KEY_CONTINUE},
-       {"goto",      SCF_LEX_WORD_KEY_GOTO},
-
-       {"switch",    SCF_LEX_WORD_KEY_SWITCH},
-       {"case",      SCF_LEX_WORD_KEY_CASE},
-       {"default",   SCF_LEX_WORD_KEY_DEFAULT},
-
-       {"return",    SCF_LEX_WORD_KEY_RETURN},
-
-       {"sizeof",    SCF_LEX_WORD_KEY_SIZEOF},
-       {"typeof",    SCF_LEX_WORD_KEY_TYPEOF},
-
-       {"new",       SCF_LEX_WORD_KEY_NEW},
-       {"operator",  SCF_LEX_WORD_KEY_OPERATOR},
-
-       {"_",         SCF_LEX_WORD_KEY_UNDERLINE},
-
-       {"char",      SCF_LEX_WORD_KEY_CHAR},
-
-       {"int",       SCF_LEX_WORD_KEY_INT},
-       {"float",     SCF_LEX_WORD_KEY_FLOAT},
-       {"double",    SCF_LEX_WORD_KEY_DOUBLE},
-       {"bit",       SCF_LEX_WORD_KEY_BIT},
-       {"bit2_t",    SCF_LEX_WORD_KEY_BIT2},
-       {"bit3_t",    SCF_LEX_WORD_KEY_BIT3},
-       {"bit4_t",    SCF_LEX_WORD_KEY_BIT4},
-
-       {"int8_t",    SCF_LEX_WORD_KEY_INT8},
-       {"int1_t",    SCF_LEX_WORD_KEY_INT1},
-       {"int2_t",    SCF_LEX_WORD_KEY_INT2},
-       {"int3_t",    SCF_LEX_WORD_KEY_INT3},
-       {"int4_t",    SCF_LEX_WORD_KEY_INT4},
-       {"int16_t",   SCF_LEX_WORD_KEY_INT16},
-       {"int32_t",   SCF_LEX_WORD_KEY_INT32},
-       {"int64_t",   SCF_LEX_WORD_KEY_INT64},
-
-       {"uint8_t",   SCF_LEX_WORD_KEY_UINT8},
-       {"uint16_t",  SCF_LEX_WORD_KEY_UINT16},
-       {"uint32_t",  SCF_LEX_WORD_KEY_UINT32},
-       {"uint64_t",  SCF_LEX_WORD_KEY_UINT64},
-
-       {"intptr_t",  SCF_LEX_WORD_KEY_INTPTR},
-       {"uintptr_t", SCF_LEX_WORD_KEY_UINTPTR},
-
-       {"void",      SCF_LEX_WORD_KEY_VOID},
-
-       {"va_start",  SCF_LEX_WORD_KEY_VA_START},
-       {"va_arg",    SCF_LEX_WORD_KEY_VA_ARG},
-       {"va_end",    SCF_LEX_WORD_KEY_VA_END},
-
-       {"container", SCF_LEX_WORD_KEY_CONTAINER},
-
-       {"class",     SCF_LEX_WORD_KEY_CLASS},
-       {"typedef",   SCF_LEX_WORD_KEY_TYPEDEF},
-
-       {"const",     SCF_LEX_WORD_KEY_CONST},
-       {"static",    SCF_LEX_WORD_KEY_STATIC},
-       {"extern",    SCF_LEX_WORD_KEY_EXTERN},
-       {"inline",    SCF_LEX_WORD_KEY_INLINE},
-
-       {"async",     SCF_LEX_WORD_KEY_ASYNC},
-       {"await",     SCF_LEX_WORD_KEY_AWAIT},
-
-       {"enum",      SCF_LEX_WORD_KEY_ENUM},
-       {"union",     SCF_LEX_WORD_KEY_UNION},
-       {"struct",    SCF_LEX_WORD_KEY_STRUCT},
-
-       {".text",     SCF_LEX_WORD_ASM_TEXT},
-       {".data",     SCF_LEX_WORD_ASM_DATA},
-       {".global",   SCF_LEX_WORD_ASM_GLOBAL},
-       {".align",    SCF_LEX_WORD_ASM_ALIGN},
-       {".org",      SCF_LEX_WORD_ASM_ORG},
-
-       {".fill",     SCF_LEX_WORD_ASM_FILL},
-       {".byte",     SCF_LEX_WORD_ASM_BYTE},
-       {".word",     SCF_LEX_WORD_ASM_WORD},
-       {".long",     SCF_LEX_WORD_ASM_LONG},
-       {".quad",     SCF_LEX_WORD_ASM_QUAD},
-       {".ascii",    SCF_LEX_WORD_ASM_ASCII},
-       {".asciz",    SCF_LEX_WORD_ASM_ASCIZ},
+       {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("elif"),      SCF_LEX_WORD_KEY_ELIF},
+       {SCF_CSTR("endif"),     SCF_LEX_WORD_KEY_ENDIF},
+
+       {SCF_CSTR("for"),       SCF_LEX_WORD_KEY_FOR},
+       {SCF_CSTR("while"),     SCF_LEX_WORD_KEY_WHILE},
+       {SCF_CSTR("do"),        SCF_LEX_WORD_KEY_DO},
+
+       {SCF_CSTR("break"),     SCF_LEX_WORD_KEY_BREAK},
+       {SCF_CSTR("continue"),  SCF_LEX_WORD_KEY_CONTINUE},
+       {SCF_CSTR("goto"),      SCF_LEX_WORD_KEY_GOTO},
+
+       {SCF_CSTR("switch"),    SCF_LEX_WORD_KEY_SWITCH},
+       {SCF_CSTR("case"),      SCF_LEX_WORD_KEY_CASE},
+       {SCF_CSTR("default"),   SCF_LEX_WORD_KEY_DEFAULT},
+
+       {SCF_CSTR("return"),    SCF_LEX_WORD_KEY_RETURN},
+
+       {SCF_CSTR("sizeof"),    SCF_LEX_WORD_KEY_SIZEOF},
+       {SCF_CSTR("typeof"),    SCF_LEX_WORD_KEY_TYPEOF},
+
+       {SCF_CSTR("new"),       SCF_LEX_WORD_KEY_NEW},
+       {SCF_CSTR("operator"),  SCF_LEX_WORD_KEY_OPERATOR},
+
+       {SCF_CSTR("_"),         SCF_LEX_WORD_KEY_UNDERLINE},
+
+       {SCF_CSTR("char"),      SCF_LEX_WORD_KEY_CHAR},
+
+       {SCF_CSTR("int"),       SCF_LEX_WORD_KEY_INT},
+       {SCF_CSTR("float"),     SCF_LEX_WORD_KEY_FLOAT},
+       {SCF_CSTR("double"),    SCF_LEX_WORD_KEY_DOUBLE},
+       {SCF_CSTR("bit"),       SCF_LEX_WORD_KEY_BIT},
+       {SCF_CSTR("bit2_t"),    SCF_LEX_WORD_KEY_BIT2},
+       {SCF_CSTR("bit3_t"),    SCF_LEX_WORD_KEY_BIT3},
+       {SCF_CSTR("bit4_t"),    SCF_LEX_WORD_KEY_BIT4},
+
+       {SCF_CSTR("int8_t"),    SCF_LEX_WORD_KEY_INT8},
+       {SCF_CSTR("int1_t"),    SCF_LEX_WORD_KEY_INT1},
+       {SCF_CSTR("int2_t"),    SCF_LEX_WORD_KEY_INT2},
+       {SCF_CSTR("int3_t"),    SCF_LEX_WORD_KEY_INT3},
+       {SCF_CSTR("int4_t"),    SCF_LEX_WORD_KEY_INT4},
+       {SCF_CSTR("int16_t"),   SCF_LEX_WORD_KEY_INT16},
+       {SCF_CSTR("int32_t"),   SCF_LEX_WORD_KEY_INT32},
+       {SCF_CSTR("int64_t"),   SCF_LEX_WORD_KEY_INT64},
+
+       {SCF_CSTR("uint8_t"),   SCF_LEX_WORD_KEY_UINT8},
+       {SCF_CSTR("uint16_t"),  SCF_LEX_WORD_KEY_UINT16},
+       {SCF_CSTR("uint32_t"),  SCF_LEX_WORD_KEY_UINT32},
+       {SCF_CSTR("uint64_t"),  SCF_LEX_WORD_KEY_UINT64},
+
+       {SCF_CSTR("intptr_t"),  SCF_LEX_WORD_KEY_INTPTR},
+       {SCF_CSTR("uintptr_t"), SCF_LEX_WORD_KEY_UINTPTR},
+
+       {SCF_CSTR("void"),      SCF_LEX_WORD_KEY_VOID},
+
+       {SCF_CSTR("va_start"),  SCF_LEX_WORD_KEY_VA_START},
+       {SCF_CSTR("va_arg"),    SCF_LEX_WORD_KEY_VA_ARG},
+       {SCF_CSTR("va_end"),    SCF_LEX_WORD_KEY_VA_END},
+
+       {SCF_CSTR("container"), SCF_LEX_WORD_KEY_CONTAINER},
+
+       {SCF_CSTR("class"),     SCF_LEX_WORD_KEY_CLASS},
+       {SCF_CSTR("typedef"),   SCF_LEX_WORD_KEY_TYPEDEF},
+
+       {SCF_CSTR("const"),     SCF_LEX_WORD_KEY_CONST},
+       {SCF_CSTR("static"),    SCF_LEX_WORD_KEY_STATIC},
+       {SCF_CSTR("extern"),    SCF_LEX_WORD_KEY_EXTERN},
+       {SCF_CSTR("inline"),    SCF_LEX_WORD_KEY_INLINE},
+
+       {SCF_CSTR("async"),     SCF_LEX_WORD_KEY_ASYNC},
+       {SCF_CSTR("await"),     SCF_LEX_WORD_KEY_AWAIT},
+
+       {SCF_CSTR("enum"),      SCF_LEX_WORD_KEY_ENUM},
+       {SCF_CSTR("union"),     SCF_LEX_WORD_KEY_UNION},
+       {SCF_CSTR("struct"),    SCF_LEX_WORD_KEY_STRUCT},
+
+       {SCF_CSTR(".text"),     SCF_LEX_WORD_ASM_TEXT},
+       {SCF_CSTR(".data"),     SCF_LEX_WORD_ASM_DATA},
+       {SCF_CSTR(".global"),   SCF_LEX_WORD_ASM_GLOBAL},
+       {SCF_CSTR(".align"),    SCF_LEX_WORD_ASM_ALIGN},
+       {SCF_CSTR(".org"),      SCF_LEX_WORD_ASM_ORG},
+
+       {SCF_CSTR(".fill"),     SCF_LEX_WORD_ASM_FILL},
+       {SCF_CSTR(".byte"),     SCF_LEX_WORD_ASM_BYTE},
+       {SCF_CSTR(".word"),     SCF_LEX_WORD_ASM_WORD},
+       {SCF_CSTR(".long"),     SCF_LEX_WORD_ASM_LONG},
+       {SCF_CSTR(".quad"),     SCF_LEX_WORD_ASM_QUAD},
+       {SCF_CSTR(".ascii"),    SCF_LEX_WORD_ASM_ASCII},
+       {SCF_CSTR(".asciz"),    SCF_LEX_WORD_ASM_ASCIZ},
 };
 
 static scf_escape_char_t  escape_chars[] =
@@ -109,13 +110,16 @@ static scf_escape_char_t  escape_chars[] =
        {'0', '\0'},
 };
 
-int _find_key_word(const char* text)
+int _find_key_word(const scf_string_t* text)
 {
+       scf_key_word_t* key;
        int i;
-       for (i = 0; i < sizeof(key_words) / sizeof(key_words[0]); i++) {
 
-               if (!strcmp(key_words[i].text, text))
-                       return key_words[i].type;
+       for (i  = 0; i < sizeof(key_words) / sizeof(key_words[0]); i++) {
+               key =              &key_words[i];
+
+               if (text->len == key->len && !memcmp(text->data, key->text, key->len))
+                       return key->type;
        }
 
        return -1;
@@ -405,29 +409,29 @@ static int _lex_identity(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0)
 
                        scf_lex_word_t* w = NULL;
 
-                       if (!strcmp(s->data, "NULL")) {
+                       if (SCF_CSTR_CMP(s, "NULL")) {
 
                                w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64);
                                if (w)
                                        w->data.u64 = 0;
 
-                       } else if (!strcmp(s->data, "__LINE__")) {
+                       } else if (SCF_CSTR_CMP(s, "__LINE__")) {
 
                                w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64);
                                if (w)
                                        w->data.u64 = lex->nb_lines;
 
-                       } else if (!strcmp(s->data, "__FILE__")) {
+                       } else if (SCF_CSTR_CMP(s, "__FILE__")) {
 
                                w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_STRING);
                                if (w)
                                        w->data.s = scf_string_clone(lex->file);
 
-                       } else if (!strcmp(s->data, "__func__")) {
+                       } else if (SCF_CSTR_CMP(s, "__func__")) {
 
                                w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_STRING);
                        } else {
-                               int type = _find_key_word(s->data);
+                               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);
@@ -798,6 +802,9 @@ int __lex_pop_word(scf_lex_t* lex, scf_lex_word_t** pword)
                case ';':
                        return _lex_op1_ll1(lex, pword, c, SCF_LEX_WORD_SEMICOLON);
                        break;
+               case '?':
+                       return _lex_op1_ll1(lex, pword, c, SCF_LEX_WORD_Q_MASK);
+                       break;
                case ':':
                        return _lex_op1_ll1(lex, pword, c, SCF_LEX_WORD_COLON);
                        break;
index 386ab3abe218d3de150aa7d082842c5f9a9f055a..1e8a67255163f9c95ffbd37273c135afe3bd39b6 100644 (file)
@@ -8,9 +8,13 @@ typedef struct scf_lex_s   scf_lex_t;
 
 typedef struct {
        char*   text;
+       int     len;
        int     type;
 } scf_key_word_t;
 
+#define SCF_CSTR(_cstr)          (_cstr), (sizeof(_cstr) - 1)
+#define SCF_CSTR_CMP(_s, _cstr)  (sizeof(_cstr) - 1 == (_s)->len && !memcmp((_s)->data, (_cstr), sizeof(_cstr) - 1))
+
 typedef struct {
        int     origin;
        int     escape;
@@ -53,7 +57,6 @@ struct scf_lex_s
 scf_char_t*  _lex_pop_char (scf_lex_t* lex);
 void         _lex_push_char(scf_lex_t* lex, scf_char_t* c);
 
-
 int     scf_lex_open (scf_lex_t** plex, const char* path, scf_string_t* text);
 int  scf_lex_close(scf_lex_t*   lex);
 
@@ -63,6 +66,12 @@ int  scf_lex_pop_word (scf_lex_t* lex, scf_lex_word_t** pword);
 int    __lex_pop_word (scf_lex_t* lex, scf_lex_word_t** pword);
 int    __lex_use_macro(scf_lex_t* lex, scf_lex_word_t** pp);
 
+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    __parse_macro_define(scf_lex_t* lex, int def_flag);
 int    __parse_macro_ifdef (scf_lex_t* lex, int def_flag);
 
@@ -70,9 +79,9 @@ int _lex_number_base_16(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s)
 int _lex_number_base_10(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s);
 int _lex_number_base_8 (scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s);
 int _lex_number_base_2 (scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s);
-int _lex_double        (scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s);
 
-int _lex_dot    (scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0);
+int _lex_double(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s);
+int _lex_dot   (scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t*   c0);
 
 int _lex_op1_ll1(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0, int type0);
 int _lex_op2_ll1(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0, int type0, char* chs, int* types, int n);
index 26e6417ed4f7db4170cb53c50b966e93f451fc84..5de3bd4d448d4d8c5f249c369f8a8914b0908ea3 100644 (file)
@@ -4,15 +4,15 @@ int _find_key_word(const char* text);
 
 static scf_key_word_t  number_postfix[] =
 {
-       {"l",   SCF_LEX_WORD_CONST_INT},
-       {"ll",  SCF_LEX_WORD_CONST_I64},
+       {SCF_CSTR("l"),   SCF_LEX_WORD_CONST_INT},
+       {SCF_CSTR("ll"),  SCF_LEX_WORD_CONST_I64},
 
-       {"u",   SCF_LEX_WORD_CONST_U32},
-       {"ul",  SCF_LEX_WORD_CONST_U32},
-       {"ull", SCF_LEX_WORD_CONST_U64},
+       {SCF_CSTR("u"),   SCF_LEX_WORD_CONST_U32},
+       {SCF_CSTR("ul"),  SCF_LEX_WORD_CONST_U32},
+       {SCF_CSTR("ull"), SCF_LEX_WORD_CONST_U64},
 
-       {"f",   SCF_LEX_WORD_CONST_FLOAT},
-       {"lf",  SCF_LEX_WORD_CONST_DOUBLE},
+       {SCF_CSTR("f"),   SCF_LEX_WORD_CONST_FLOAT},
+       {SCF_CSTR("lf"),  SCF_LEX_WORD_CONST_DOUBLE},
 };
 
 static int _lex_number_postfix(const char* postfix, int n)
@@ -23,7 +23,7 @@ static int _lex_number_postfix(const char* postfix, int n)
        for (i  = 0; i < sizeof(number_postfix) / sizeof(number_postfix[0]); i++) {
                key =              &number_postfix[i];
 
-               if (!strncmp(key->text, postfix, n))
+               if (n == key->len && !memcmp(postfix, key->text, n))
                        return key->type;
        }
 
index b8c1a718e8e2290cf954a8be20b94aebd3b26f93..dff36f52cee6fa6b0602dbc36d3afa56105ad2e0 100644 (file)
@@ -1,6 +1,24 @@
 #include"scf_lex.h"
 
-static int __macro_drop_to_LF(scf_lex_t* lex)
+scf_macro_t* __find_macro(scf_lex_t* lex, scf_lex_word_t* w)
+{
+       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 (m->def_flag && !scf_string_cmp(m->w->text, w->text))
+                       return m;
+       }
+
+       return NULL;
+}
+
+int __macro_drop_to_LF(scf_lex_t* lex)
 {
        scf_lex_word_t* w = NULL;
        int type;
@@ -14,12 +32,15 @@ static int __macro_drop_to_LF(scf_lex_t* lex)
                scf_lex_word_free(w);
                w = NULL;
 
+               if (SCF_LEX_WORD_EOF == type)
+                       return -EINVAL;
+
        } while (SCF_LEX_WORD_LF != type);
 
        return 0;
 }
 
-static int __macro_drop_to(scf_lex_t* lex, 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)
 {
        scf_lex_word_t* w1 = NULL;
        scf_lex_word_t* w2 = NULL;
@@ -33,6 +54,11 @@ static int __macro_drop_to(scf_lex_t* lex, scf_lex_word_t** pw1, scf_lex_word_t*
                                return ret;
                }
 
+               if (SCF_LEX_WORD_EOF == w1->type) {
+                       scf_lex_word_free(w1);
+                       return -EINVAL;
+               }
+
                if (SCF_LEX_WORD_HASH != w1->type) {
                        scf_lex_word_free(w1);
                        w1 = NULL;
@@ -75,7 +101,7 @@ end:
        return 0;
 }
 
-static 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_pop_to(scf_lex_t* lex, scf_lex_word_t** h, scf_lex_word_t** pw1, scf_lex_word_t** pw2)
 {
        scf_lex_word_t* w1 = NULL;
        scf_lex_word_t* w2 = NULL;
@@ -89,6 +115,11 @@ static int __macro_pop_to(scf_lex_t* lex, scf_lex_word_t** h, scf_lex_word_t** p
                                return ret;
                }
 
+               if (SCF_LEX_WORD_EOF == w1->type) {
+                       scf_lex_word_free(w1);
+                       return -EINVAL;
+               }
+
                if (SCF_LEX_WORD_HASH != w1->type) {
                        w1->next = *h;
                        *h = w1;
@@ -278,15 +309,10 @@ int __parse_macro_define(scf_lex_t* lex, int def_flag)
        }
 
        if (lex->macros) {
-               int i;
-               for (i = lex->macros->size - 1; i >= 0; i--) {
-                       m0 = lex->macros->data[i];
-
-                       if (!scf_string_cmp(m->w->text, m0->w->text)) {
-                               scf_logw("macro '%s' defined before in file: %s, line: %d\n",
-                                               m0->w->text->data, m0->w->file->data, m0->w->line);
-                               break;
-                       }
+               m0 = __find_macro(lex, m->w);
+               if (m0) {
+                       scf_logw("macro '%s' defined before in file: %s, line: %d\n",
+                                       m0->w->text->data, m0->w->file->data, m0->w->line);
                }
        } else {
                lex->macros = scf_vector_alloc();
@@ -328,18 +354,8 @@ int __parse_macro_ifdef(scf_lex_t* lex, int def_flag)
                return ret;
 
        int found = 0;
-       int i;
-
-       if (lex->macros) {
-               for (i = lex->macros->size - 1; i >= 0; i--) {
-                       m  = lex->macros->data[i];
-
-                       if (m->def_flag && !scf_string_cmp(m->w->text, w->text)) {
-                               found = 1;
-                               break;
-                       }
-               }
-       }
+       if (lex->macros && __find_macro(lex, w))
+               found = 1;
 
        scf_logw("macro '%s', found: %d, def_flag: %d, file: %s, line: %d\n",
                        w->text->data, found, def_flag, w->file->data, w->line);
@@ -541,24 +557,6 @@ static int __convert_str(scf_lex_word_t* h)
        return 0;
 }
 
-static scf_macro_t* __find_macro(scf_lex_t* lex, scf_lex_word_t* w)
-{
-       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))
-                       return m;
-       }
-
-       return NULL;
-}
-
 static int __use_macro(scf_lex_t* lex, scf_macro_t* m, scf_lex_word_t* use)
 {
        scf_lex_word_t** pp;
diff --git a/lex/scf_macro_expr.c b/lex/scf_macro_expr.c
new file mode 100644 (file)
index 0000000..cb1e217
--- /dev/null
@@ -0,0 +1,612 @@
+#include"scf_lex.h"
+
+scf_macro_t* __find_macro(scf_lex_t* lex, scf_lex_word_t* w);
+
+typedef struct {
+       scf_lex_word_t**  pp;
+       scf_lex_word_t*   error;
+
+       int               n_lps;
+       int               n_rps;
+} scf_macro_ctx_t;
+
+typedef int (*scf_macro_operator_pt)(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand);
+static  int             __macro_expr(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w,    int n_consts, scf_lex_word_t** operand);
+
+static int macro_binary_priority[SCF_LEX_N_OPS] =
+{
+       [SCF_LEX_WORD_STAR     ] = 1,
+       [SCF_LEX_WORD_DIV      ] = 1,
+       [SCF_LEX_WORD_MOD      ] = 1,
+
+       [SCF_LEX_WORD_PLUS     ] = 2,
+       [SCF_LEX_WORD_MINUS    ] = 2,
+
+       [SCF_LEX_WORD_SHL      ] = 3,
+       [SCF_LEX_WORD_SHR      ] = 3,
+
+       [SCF_LEX_WORD_BIT_XOR  ] = 4,
+       [SCF_LEX_WORD_BIT_AND  ] = 4,
+       [SCF_LEX_WORD_BIT_OR   ] = 4,
+
+       [SCF_LEX_WORD_EQ       ] = 5,
+       [SCF_LEX_WORD_NE       ] = 5,
+       [SCF_LEX_WORD_GT       ] = 5,
+       [SCF_LEX_WORD_LT       ] = 5,
+       [SCF_LEX_WORD_GE       ] = 5,
+       [SCF_LEX_WORD_LE       ] = 5,
+
+       [SCF_LEX_WORD_LOGIC_AND] = 6,
+       [SCF_LEX_WORD_LOGIC_OR ] = 6,
+
+       [SCF_LEX_WORD_Q_MASK   ] = 7,
+       [SCF_LEX_WORD_COLON    ] = 8,
+};
+
+static int __macro_unary_operand(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t** operand)
+{
+       assert(!*operand);
+
+       scf_lex_word_t* w0 = NULL;
+
+       int ret = __lex_pop_word(lex, &w0);
+       if (ret < 0)
+               return ret;
+
+       switch (w0->type)
+       {
+               case SCF_LEX_WORD_PLUS:
+               case SCF_LEX_WORD_MINUS:
+               case SCF_LEX_WORD_LOGIC_NOT:
+               case SCF_LEX_WORD_BIT_NOT:
+               case SCF_LEX_WORD_KEY_DEFINED:
+               case SCF_LEX_WORD_LP:
+                       ret = __macro_expr(lex, ctx, w0, 1, operand);
+                       if (ret < 0)
+                               return ret;
+                       break;
+
+               case SCF_LEX_WORD_ID:
+                       ret = __lex_use_macro(lex, &w0);
+                       if (ret < 0)
+                               return ret;
+
+               default:
+                       scf_logw("w0: %s, w0->data.u64: %ld\n", w0->text->data, w0->data.u64);
+
+                       *operand = w0;
+
+                       w0->next = NULL;
+
+                       *ctx->pp = w0;
+                       ctx->pp = &w0->next;
+                       break;
+       };
+
+       return 0;
+}
+
+static int __macro_binary_operand(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* op, scf_lex_word_t** operand2)
+{
+       assert(!*operand2);
+
+       scf_lex_word_t* op2 = NULL;
+
+       int ret = __macro_unary_operand(lex, ctx, operand2);
+       if (ret < 0)
+               return ret;
+
+       ret = __lex_pop_word(lex, &op2);
+       if (ret < 0)
+               return ret;
+
+       if (SCF_LEX_WORD_RP == op2->type) {
+               op2->next = NULL;
+
+               *ctx->pp = op2;
+               ctx->pp = &op2->next;
+               return 0;
+       }
+
+       if (op2->type < SCF_LEX_N_OPS) {
+               int cur  = macro_binary_priority[op ->type];
+               int next = macro_binary_priority[op2->type];
+
+               if (next > 0 && next < cur)
+                       return __macro_expr(lex, ctx, op2, 2, operand2);
+       }
+
+       scf_lex_push_word(lex, op2);
+       return 0;
+}
+
+#define MACRO_OPERATOR_BINARY(name, op) \
+static int __macro_binary_##name(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand) \
+{ \
+       assert(2 == n_consts); \
+       assert(*operand); \
+       \
+       scf_lex_word_t*  w0 = *operand; \
+       scf_lex_word_t*  w1 = NULL; \
+       \
+       int ret = __macro_binary_operand(lex, ctx, w_op, &w1); \
+       if (ret < 0) \
+               return ret; \
+       \
+       if (!scf_lex_is_const(w0)) { \
+               scf_loge("\n"); \
+               return -EINVAL; \
+       } \
+       \
+       if (!scf_lex_is_const(w1)) { \
+               scf_loge("\n"); \
+               return -EINVAL; \
+       } \
+       \
+       w0->data.i64 = w0->data.i64 op w1->data.i64; \
+       scf_logi("op: %s, result: %ld, line: %d, pos: %d\n", w_op->text->data, w0->data.i64, w_op->line, w_op->pos); \
+       \
+       *operand = w0; \
+       return 0; \
+}
+
+MACRO_OPERATOR_BINARY(mul, *)
+MACRO_OPERATOR_BINARY(div, /)
+MACRO_OPERATOR_BINARY(mod, %)
+
+MACRO_OPERATOR_BINARY(plus,  +)
+MACRO_OPERATOR_BINARY(minus, -)
+
+MACRO_OPERATOR_BINARY(shl, <<)
+MACRO_OPERATOR_BINARY(shr, >>)
+
+MACRO_OPERATOR_BINARY(bit_xor, ^)
+MACRO_OPERATOR_BINARY(bit_and, &)
+MACRO_OPERATOR_BINARY(bit_or,  |)
+
+MACRO_OPERATOR_BINARY(eq, ==)
+MACRO_OPERATOR_BINARY(ne, !=)
+MACRO_OPERATOR_BINARY(gt, >)
+MACRO_OPERATOR_BINARY(lt, <)
+MACRO_OPERATOR_BINARY(ge, >=)
+MACRO_OPERATOR_BINARY(le, <=)
+
+MACRO_OPERATOR_BINARY(logic_and, &&)
+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 = __lex_pop_word(lex, &w0);
+       if (ret < 0)
+               return ret;
+
+       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);
+
+               ret = -EINVAL;
+               goto error;
+       }
+
+       if (__find_macro(lex, w0))
+               w0->data.i64 = 1;
+       else
+               w0->data.i64 = 0;
+
+       w0->type = SCF_LEX_WORD_CONST_I64;
+       *operand = w0;
+
+       scf_logi("w0: %s, result: %ld\n", w0->text->data, w0->data.i64);
+
+       ret = 0;
+
+error:
+       w0->next = NULL;
+       *ctx->pp = w0;
+       ctx->pp = &w0->next;
+       return ret;
+}
+
+#define MACRO_OPERATOR_UNARY(name, op) \
+static int __macro_unary_##name(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand) \
+{ \
+       assert(1 == n_consts); \
+       assert(!*operand); \
+       \
+       int ret = __macro_unary_operand(lex, ctx, operand); \
+       if (ret < 0) \
+               return ret; \
+       \
+       if (!*operand) { \
+               scf_loge("unary operand NOT found for '%s', file: %s, line: %d\n", \
+                               w_op->text->data, w_op->file->data, w_op->line); \
+               return -EINVAL; \
+       } \
+       \
+       scf_lex_word_t*  w0 = *operand; \
+       \
+       if (!scf_lex_is_const(w0)) { \
+               scf_loge("\n"); \
+               return -EINVAL; \
+       } \
+       \
+       w0->data.u64 = op w0->data.u64; \
+       scf_logi("op: %s, result: %ld, line: %d, pos: %d\n", w_op->text->data, w0->data.i64, w_op->line, w_op->pos); \
+       return 0; \
+}
+
+MACRO_OPERATOR_UNARY(logic_not, !)
+MACRO_OPERATOR_UNARY(bit_not,   ~)
+
+MACRO_OPERATOR_UNARY(plus,  +)
+MACRO_OPERATOR_UNARY(minus, -)
+
+static int __macro_operator_plus(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand)
+{
+       if (1 == n_consts)
+               return __macro_unary_plus(lex, ctx, w_op, n_consts, operand);
+
+       else if (2 == n_consts)
+               return __macro_binary_plus(lex, ctx, w_op, n_consts, operand);
+
+       scf_loge("\n");
+       return -EINVAL;
+}
+
+static int __macro_operator_minus(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand)
+{
+       if (1 == n_consts)
+               return __macro_unary_minus(lex, ctx, w_op, n_consts, operand);
+
+       else if (2 == n_consts)
+               return __macro_binary_minus(lex, ctx, w_op, n_consts, operand);
+
+       scf_loge("\n");
+       return -EINVAL;
+}
+
+static int __macro_operator_cond(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand)
+{
+       if (!*operand) {
+               scf_loge("NO 'cond expr' before '?', file: %s, line: %d\n", w_op->file->data, w_op->line);
+               return -EINVAL;
+       }
+
+       scf_lex_word_t*  cond   = *operand;
+       scf_lex_word_t*  _true  = NULL;
+       scf_lex_word_t*  _false = NULL;
+       scf_lex_word_t*  op2    = NULL;
+
+       int ret = __macro_unary_operand(lex, ctx, &_true);
+       if (ret < 0)
+               return ret;
+
+       ret = __lex_pop_word(lex, &op2);
+       if (ret < 0)
+               return ret;
+
+       if (op2->type < SCF_LEX_N_OPS) {
+               int cur  = macro_binary_priority[w_op->type];
+               int next = macro_binary_priority[op2->type];
+
+               if (next > 0 && next < cur) {
+                       ret = __macro_expr(lex, ctx, op2, 2, &_true);
+                       if (ret < 0)
+                               return ret;
+
+                       ret = __lex_pop_word(lex, &op2);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
+       op2->next = NULL;
+       *ctx->pp = op2;
+       ctx->pp = &op2->next;
+
+       switch (op2->type)
+       {
+               case SCF_LEX_WORD_Q_MASK:
+
+                       ret = __macro_operator_cond(lex, ctx, op2, 2, &_true);
+                       if (ret < 0)
+                               return ret;
+                       break;
+
+               case SCF_LEX_WORD_COLON:
+                       break;
+               default:
+                       scf_loge("'%s' is NOT ':' after '?', file: %s, line: %d, pos: %d\n",
+                                       op2->text->data, op2->file->data, op2->line, op2->pos);
+                       return -EINVAL;
+                       break;
+       };
+
+       ret = __macro_unary_operand(lex, ctx, &_false);
+       if (ret < 0)
+               return ret;
+
+       if (cond->data.u64)
+               *operand = _true;
+       else
+               *operand = _false;
+
+       scf_logi("op: %s, flag: %d, result: %ld, line: %d, pos: %d\n",
+                       w_op->text->data, !!cond->data.u64, (*operand)->data.i64, w_op->line, w_op->pos);
+       return 0;
+}
+
+static int __macro_operator_lp(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand);
+
+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)
+{
+       return 0;
+}
+
+static scf_macro_operator_pt  macro_operators[] =
+{
+       [SCF_LEX_WORD_LP         ] = __macro_operator_lp,
+       [SCF_LEX_WORD_RP         ] = __macro_operator_rp,
+
+       [SCF_LEX_WORD_LOGIC_NOT  ] = __macro_unary_logic_not,
+       [SCF_LEX_WORD_BIT_NOT    ] = __macro_unary_bit_not,
+       [SCF_LEX_WORD_KEY_DEFINED] = __macro_operator_defined,
+
+       [SCF_LEX_WORD_STAR       ] = __macro_binary_mul,
+       [SCF_LEX_WORD_DIV        ] = __macro_binary_div,
+       [SCF_LEX_WORD_MOD        ] = __macro_binary_mod,
+
+       [SCF_LEX_WORD_PLUS       ] = __macro_operator_plus,
+       [SCF_LEX_WORD_MINUS      ] = __macro_operator_minus,
+
+       [SCF_LEX_WORD_SHL        ] = __macro_binary_shl,
+       [SCF_LEX_WORD_SHR        ] = __macro_binary_shr,
+
+       [SCF_LEX_WORD_BIT_XOR    ] = __macro_binary_bit_xor,
+       [SCF_LEX_WORD_BIT_AND    ] = __macro_binary_bit_and,
+       [SCF_LEX_WORD_BIT_OR     ] = __macro_binary_bit_or,
+
+       [SCF_LEX_WORD_GT         ] = __macro_binary_gt,
+       [SCF_LEX_WORD_LT         ] = __macro_binary_lt,
+       [SCF_LEX_WORD_GE         ] = __macro_binary_ge,
+       [SCF_LEX_WORD_LE         ] = __macro_binary_le,
+       [SCF_LEX_WORD_EQ         ] = __macro_binary_eq,
+       [SCF_LEX_WORD_NE         ] = __macro_binary_ne,
+
+       [SCF_LEX_WORD_LOGIC_AND  ] = __macro_binary_logic_and,
+       [SCF_LEX_WORD_LOGIC_OR   ] = __macro_binary_logic_or,
+
+       [SCF_LEX_WORD_Q_MASK     ] = __macro_operator_cond,
+};
+
+static int __macro_operator_lp(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand)
+{
+       assert(!*operand);
+
+       int ret = __macro_unary_operand(lex, ctx, operand);
+       if (ret < 0)
+               return ret;
+
+       if (!*operand) {
+               scf_loge("unary operand NOT found for '%s', file: %s, line: %d\n",
+                               w_op->text->data, w_op->file->data, w_op->line);
+               return -EINVAL;
+       }
+
+       scf_lex_word_t*  w0  = *operand;
+       scf_lex_word_t*  op2 = NULL;
+
+       if (!scf_lex_is_const(w0)) {
+               scf_loge("\n");
+               return -EINVAL;
+       }
+
+       ret = __lex_pop_word(lex, &op2);
+       if (ret < 0)
+               return ret;
+
+       op2->next = NULL;
+       *ctx->pp = op2;
+       ctx->pp = &op2->next;
+
+       scf_macro_operator_pt  f;
+
+       switch (op2->type)
+       {
+               case SCF_LEX_WORD_RP:
+                       break;
+
+               case SCF_LEX_WORD_STAR:
+               case SCF_LEX_WORD_DIV:
+               case SCF_LEX_WORD_MOD:
+               case SCF_LEX_WORD_PLUS:
+               case SCF_LEX_WORD_MINUS:
+
+               case SCF_LEX_WORD_SHL:
+               case SCF_LEX_WORD_SHR:
+               case SCF_LEX_WORD_BIT_XOR:
+               case SCF_LEX_WORD_BIT_AND:
+               case SCF_LEX_WORD_BIT_OR:
+
+               case SCF_LEX_WORD_EQ:
+               case SCF_LEX_WORD_NE:
+               case SCF_LEX_WORD_GT:
+               case SCF_LEX_WORD_LT:
+               case SCF_LEX_WORD_GE:
+               case SCF_LEX_WORD_LE:
+
+               case SCF_LEX_WORD_LOGIC_AND:
+               case SCF_LEX_WORD_LOGIC_OR:
+                       f = macro_operators[op2->type];
+                       if (!f) {
+                               scf_loge("operator '%s' NOT supported in macro expr, file: %s, line: %d\n",
+                                               op2->text->data, op2->file->data, op2->line);
+                               return -EINVAL;
+                       }
+
+                       return f(lex, ctx, op2, 2, operand);
+                       break;
+
+               default:
+                       scf_loge("\n");
+                       return -EINVAL;
+                       break;
+       };
+
+       return 0;
+}
+
+static int __macro_expr(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w, int n_consts, scf_lex_word_t** operand)
+{
+       int ret;
+
+       if (SCF_LEX_WORD_EOF == w->type) {
+               scf_loge("\n");
+
+               scf_lex_word_free(w);
+               return -EINVAL;
+       }
+
+       if (SCF_LEX_WORD_LF == w->type) {
+               scf_loge("\n");
+
+               scf_lex_push_word(lex, w);
+               return -EINVAL;
+       }
+
+       if (scf_lex_is_operator(w)) {
+
+               w->next = NULL;
+               *ctx->pp = w;
+               ctx->pp = &w->next;
+
+               scf_macro_operator_pt f = macro_operators[w->type];
+               if (!f) {
+                       scf_loge("operator '%s' NOT supported in macro expr, file: %s, line: %d\n",
+                                       w->text->data, w->file->data, w->line);
+                       return -EINVAL;
+               }
+
+               return f(lex, ctx, w, n_consts, operand);
+       }
+
+       if (SCF_LEX_WORD_ID == w->type) {
+
+               ret = __lex_use_macro(lex, &w);
+               if (ret < 0)
+                       return ret;
+       }
+
+       *operand = w;
+
+       w->next = NULL;
+       *ctx->pp = w;
+       ctx->pp = &w->next;
+       return 0;
+}
+
+int __macro_if_expr(scf_lex_t* lex)
+{
+       scf_lex_word_t*  operand = NULL;
+       scf_lex_word_t*  w   = NULL;
+       scf_lex_word_t*  h   = NULL;
+       scf_macro_ctx_t  ctx = {&h, 0, 0};
+
+       int ret = 0;
+
+       while (1) {
+               ret = __lex_pop_word(lex, &w);
+               if (ret < 0)
+                       goto error;
+
+               if (SCF_LEX_WORD_LF == w->type) {
+                       scf_lex_push_word(lex, w);
+                       w = NULL;
+                       break;
+               }
+
+               if (SCF_LEX_WORD_EOF == w->type) {
+                       scf_loge("un-wanted '%s' in macro expr, file: %s, line: %d\n",
+                                       w->text->data, w->file->data, w->line);
+
+                       ret = -EINVAL;
+                       goto error;
+               }
+
+               if (scf_lex_is_operator(w)) {
+                       scf_macro_operator_pt f = macro_operators[w->type];
+                       if (!f) {
+                               scf_loge("operator '%s' NOT supported in macro expr, file: %s, line: %d\n",
+                                               w->text->data, w->file->data, w->line);
+
+                               ret = -EINVAL;
+                               goto error;
+                       }
+
+                       w->next = NULL;
+                       *ctx.pp = w;
+                       ctx.pp = &w->next;
+
+                       if (operand)
+                               ret = f(lex, &ctx, w, 2, &operand);
+                       else
+                               ret = f(lex, &ctx, w, 1, &operand);
+
+                       w = NULL;
+                       if (ret < 0)
+                               goto error;
+                       continue;
+               }
+
+               if (SCF_LEX_WORD_ID == w->type) {
+
+                       ret = __lex_use_macro(lex, &w);
+                       if (ret < 0)
+                               goto error;
+               }
+
+               if (!scf_lex_is_const(w)) {
+                       scf_loge("operand '%s' is NOT CONST in macro expr, 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;
+
+               w->next = NULL;
+               *ctx.pp = w;
+               ctx.pp = &w->next;
+               w = NULL;
+       }
+
+       if (operand)
+               ret = !!operand->data.u64;
+       else
+               ret = 0;
+
+error:
+       if (w) {
+               w->next = NULL;
+               *ctx.pp = w;
+               w = NULL;
+       }
+
+       while (h) {
+               w = h;
+               h = w->next;
+
+               scf_logi("\033[34m macro: %s, position: %d,%d\033[0m\n", w->text->data, w->line, w->pos);
+
+               scf_lex_word_free(w);
+               w = NULL;
+       }
+
+       scf_logi("final flag: %d\n", ret);
+       return ret;
+}
index 89147f9bcadf7598f9c7e04c8a8fcd892754f39f..c66cd26737b0300874288da2d49e04cf180d5fbc 100644 (file)
@@ -458,13 +458,13 @@ static int _x64_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                return -EINVAL;
        }
 
-       scf_x64_context_t* x64    = ctx->priv;
-       scf_function_t*    f      = x64->f;
-       scf_3ac_operand_t* src  = c->srcs->data[0];
-       scf_variable_t*    var_pf = src0->dag_node->var;
-       scf_function_t*    pf     = var_pf->func_ptr;
+       scf_x64_context_t* x64  = ctx->priv;
+       scf_function_t*    f    = x64->f;
+       scf_3ac_operand_t* src  = c->srcs->data[0];
+       scf_dag_node_t*    dn   = src->dag_node;
+       scf_function_t*    pf   = dn->var->func_ptr;
 
-       if (SCF_FUNCTION_PTR != var_pf->type || !pf) {
+       if (SCF_FUNCTION_PTR != dn->var->type || !pf) {
                scf_loge("\n");
                return -EINVAL;
        }
@@ -486,26 +486,17 @@ static int _x64_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        scf_instruction_t*  inst;
        scf_instruction_t*  inst_rsp = NULL;
 
-       int data_rela_size = f->data_relas->size;
-       int text_rela_size = f->text_relas->size;
-       scf_logd("f->data_relas->size: %d, f->text_relas->size: %d\n", f->data_relas->size, f->text_relas->size);
-
        int ret;
-       int i;
 
        if (pf->rets) {
                ret = _x64_call_save_ret_regs(c, f, pf);
-               if (ret < 0) {
-                       scf_loge("\n");
+               if (ret < 0)
                        return ret;
-               }
        }
 
        ret = x64_overflow_reg(rax, c, f);
-       if (ret < 0) {
-               scf_loge("\n");
+       if (ret < 0)
                return ret;
-       }
 
        x64_call_rabi(NULL, NULL, c);
 
@@ -517,10 +508,9 @@ static int _x64_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        }
 
        ret = _x64_inst_call_argv(c, f);
-       if (ret < 0) {
-               scf_loge("\n");
+       if (ret < 0)
                return ret;
-       }
+
        uint32_t imm = ret > 0;
 
        mov  = x64_find_OpCode(SCF_X64_MOV, 4,4, SCF_X64_I2G);
@@ -543,8 +533,8 @@ static int _x64_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                memcpy(inst_rsp->code + inst_rsp->len - 4, &size, 4);
        }
 
-       if (var_pf->const_literal_flag) {
-               assert(0 == src0->dag_node->color);
+       if (dn->var->const_literal_flag) {
+               assert(0 == dn->color);
 
                int32_t offset = 0;
                call = x64_find_OpCode(SCF_X64_CALL, 4,4, SCF_X64_I);
@@ -560,33 +550,27 @@ static int _x64_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                rela->inst_offset = 1;
                X64_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf);
        } else {
-               assert(0 != src0->dag_node->color);
-
-               call = x64_find_OpCode(SCF_X64_CALL, 8,8, SCF_X64_E);
+               assert(0 != dn->color);
 
-               if (src0->dag_node->color > 0) {
+               scf_register_t* r_pf = NULL;
+               scf_rela_t*     rela = NULL;
 
-                       scf_register_t* r_pf = NULL;
+               call = x64_find_OpCode(SCF_X64_CALL, 8,8, SCF_X64_E);
 
-                       ret = x64_select_reg(&r_pf, src0->dag_node, c, f, 1);
-                       if (ret < 0) {
-                               scf_loge("\n");
+               if (dn->color > 0) {
+                       ret = x64_select_reg(&r_pf, dn, c, f, 1);
+                       if (ret < 0)
                                return ret;
-                       }
 
                        inst = x64_make_inst_E(call, r_pf);
                        X64_INST_ADD_CHECK(c, inst, NULL);
-
-                       inst->OpCode = (scf_OpCode_t*)call;
                } else {
-                       scf_rela_t* rela = NULL;
-
-                       inst = x64_make_inst_M(&rela, call, var_pf, NULL);
+                       inst = x64_make_inst_M(&rela, call, dn->var, NULL);
                        X64_INST_ADD_CHECK(c, inst, rela);
-                       X64_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf);
-
-                       inst->OpCode = (scf_OpCode_t*)call;
+                       X64_RELA_ADD_CHECK(f->data_relas, rela, c, dn->var, NULL);
                }
+
+               inst->OpCode = (scf_OpCode_t*)call;
        }
 
        if (stack_size > 0) {
@@ -603,18 +587,14 @@ static int _x64_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        if (pf->rets && pf->rets->size > 0 && c->dsts) {
 
                nb_updated = _x64_call_update_dsts(c, f, updated_regs, X64_ABI_RET_NB * 2);
-               if (nb_updated < 0) {
-                       scf_loge("\n");
+               if (nb_updated < 0)
                        return nb_updated;
-               }
        }
 
        if (save_size > 0) {
                ret = x64_pop_regs(c, saved_regs, save_size >> 3, updated_regs, nb_updated);
-               if (ret < 0) {
-                       scf_loge("\n");
+               if (ret < 0)
                        return ret;
-               }
        }
 
        f->call_flag = 1;
index 4f6e8328c23203f5af02db0a4794593132daa844..5374945457beed611c430e756633451010e18f47 100644 (file)
@@ -3,6 +3,7 @@ CFILES += ../util/scf_graph.c
 CFILES += ../lex/scf_lex.c
 CFILES += ../lex/scf_lex_util.c
 CFILES += ../lex/scf_macro.c
+CFILES += ../lex/scf_macro_expr.c
 
 CFILES += scf_parse_util.c
 CFILES += scf_parse.c
index 14f4394d86002e0229f9b347dd1ee1b8adfc180c..40b293df627395f294fc93c0fb40483802bd6b8c 100644 (file)
@@ -8,6 +8,9 @@ typedef struct {
 
        scf_block_t*     parent_block;
 
+       int              pf_pointers;
+       int              pf_lps;
+       int              pf_rps;
 } dfa_fun_data_t;
 
 int _function_add_function(scf_dfa_t* dfa, dfa_data_t* d)
@@ -17,31 +20,81 @@ int _function_add_function(scf_dfa_t* dfa, dfa_data_t* d)
                return SCF_DFA_ERROR;
        }
 
-       scf_parse_t*    parse = dfa->priv;
-       scf_ast_t*      ast   = parse->ast;
-       dfa_identity_t* id    = scf_stack_pop(d->current_identities);
-       dfa_fun_data_t* fd    = d->module_datas[dfa_module_function.index];
+       scf_parse_t*     parse = dfa->priv;
+       scf_ast_t*       ast   = parse->ast;
+       dfa_identity_t*  id    = scf_stack_pop(d->current_identities);
+       dfa_fun_data_t*  fd    = d->module_datas[dfa_module_function.index];
 
-       scf_function_t* f;
-       scf_variable_t* v;
-       scf_block_t*    b;
+       scf_variable_t*  v_pf = NULL;
+       scf_function_t*  f;
+       scf_variable_t*  v;
+       scf_block_t*     b;
+       scf_type_t*      t;
 
        if (!id || !id->identity) {
                scf_loge("function identity not found\n");
                return SCF_DFA_ERROR;
        }
 
+       uint32_t local_flag  = 0;
+       uint32_t global_flag = 0;
+       uint32_t member_flag = 0;
+
        b = ast->current_block;
        while (b) {
-               if (b->node.type >= SCF_STRUCT)
+               if (b->node.type >= SCF_STRUCT || SCF_FUNCTION == b->node.type)
                        break;
                b = (scf_block_t*)b->node.parent;
        }
 
+       if (!b) {
+               local_flag  = 0;
+               global_flag = 1;
+               member_flag = 0;
+
+       } else if (SCF_FUNCTION == b->node.type) {
+               local_flag  = 1;
+               global_flag = 0;
+               member_flag = 0;
+
+       } else if (b->node.type >= SCF_STRUCT) {
+               local_flag  = 0;
+               global_flag = 0;
+               member_flag = 1;
+       }
+
+       assert(global_flag || local_flag || member_flag);
+
+       if (fd->pf_pointers > 0) {
+               t = NULL;
+
+               int pf_pointers = fd->pf_pointers;
+
+               fd->pf_pointers = 0;
+
+               int ret = scf_ast_find_type_type(&t, ast, SCF_FUNCTION_PTR);
+               if (ret < 0)
+                       return ret;
+
+               v_pf = SCF_VAR_ALLOC_BY_TYPE(id->identity, t, 0, pf_pointers, NULL);
+               if (!v_pf)
+                       return -ENOMEM;
+
+               scf_scope_push_var(ast->current_block->scope, v_pf);
+
+               ret = scf_string_cat_cstr(id->identity->text, "_pt");
+               if (ret < 0)
+                       return ret;
+
+               v_pf->local_flag  = local_flag;
+               v_pf->global_flag = global_flag;
+               v_pf->member_flag = member_flag;
+       }
+
        f = scf_function_alloc(id->identity);
        if (!f)
                return SCF_DFA_ERROR;
-       f->member_flag = !!b;
+       f->member_flag = member_flag;
 
        free(id);
        id = NULL;
@@ -109,9 +162,28 @@ int _function_add_function(scf_dfa_t* dfa, dfa_data_t* d)
                SCF_XCHG(f->rets->data[i], f->rets->data[j]);
        }
 
-       scf_scope_push_function(ast->current_block->scope, f);
+       if (!f->member_flag || v_pf) {
+
+               b = ast->current_block;
+               while (b) {
+                       if (b->node.file_flag)
+                               break;
+                       b = (scf_block_t*)b->node.parent;
+               }
+
+               scf_scope_push_function(b->scope, f);
+
+               scf_node_add_child((scf_node_t*)b, (scf_node_t*)f);
 
-       scf_node_add_child((scf_node_t*)ast->current_block, (scf_node_t*)f);
+               if (v_pf) {
+                       v_pf->static_flag = f->static_flag;
+                       v_pf->func_ptr    = f;
+               }
+       } else {
+               scf_scope_push_function(ast->current_block->scope, f);
+
+               scf_node_add_child((scf_node_t*)ast->current_block, (scf_node_t*)f);
+       }
 
        fd ->parent_block  = ast->current_block;
        ast->current_block = (scf_block_t*)f;
@@ -223,6 +295,49 @@ static int _function_action_comma(scf_dfa_t* dfa, scf_vector_t* words, void* dat
        return SCF_DFA_NEXT_WORD;
 }
 
+static int _function_action_pf_star(scf_dfa_t* dfa, scf_vector_t* words, void* data)
+{
+       dfa_data_t*      d     = data;
+       dfa_fun_data_t*  fd    = d->module_datas[dfa_module_function.index];
+
+       fd->pf_pointers++;
+
+       return SCF_DFA_NEXT_WORD;
+}
+
+static int _function_action_pf_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
+{
+       dfa_data_t*      d     = data;
+       dfa_fun_data_t*  fd    = d->module_datas[dfa_module_function.index];
+
+       fd->pf_lps++;
+
+       SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_pf_rp"), SCF_DFA_HOOK_PRE);
+
+       return SCF_DFA_NEXT_WORD;
+}
+
+static int _function_action_pf_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
+{
+       dfa_data_t*      d     = data;
+       dfa_fun_data_t*  fd    = d->module_datas[dfa_module_function.index];
+       dfa_identity_t*  id    = scf_stack_top(d->current_identities);
+
+       fd->pf_rps++;
+
+       if (fd->pf_rps == fd->pf_lps) {
+               fd->pf_rps = 0;
+               fd->pf_lps = 0;
+
+               if (id && id->identity)
+                       scf_logw("pf: %s(), nb_pointers: %d\n", id->identity->text->data, fd->pf_pointers);
+       } else {
+               SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "function_pf_rp"), SCF_DFA_HOOK_PRE);
+       }
+
+       return SCF_DFA_NEXT_WORD;
+}
+
 static int _function_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
 {
        scf_parse_t*     parse = dfa->priv;
@@ -390,12 +505,16 @@ static int _function_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data)
 
 static int _dfa_init_module_function(scf_dfa_t* dfa)
 {
-       SCF_DFA_MODULE_NODE(dfa, function, comma,  scf_dfa_is_comma, _function_action_comma);
-       SCF_DFA_MODULE_NODE(dfa, function, vargs,  scf_dfa_is_vargs, _function_action_vargs);
-       SCF_DFA_MODULE_NODE(dfa, function, end,    scf_dfa_is_entry, _function_action_end);
+       SCF_DFA_MODULE_NODE(dfa, function, comma,    scf_dfa_is_comma, _function_action_comma);
+       SCF_DFA_MODULE_NODE(dfa, function, vargs,    scf_dfa_is_vargs, _function_action_vargs);
+       SCF_DFA_MODULE_NODE(dfa, function, end,      scf_dfa_is_entry, _function_action_end);
+
+       SCF_DFA_MODULE_NODE(dfa, function, lp,       scf_dfa_is_lp,    _function_action_lp);
+       SCF_DFA_MODULE_NODE(dfa, function, rp,       scf_dfa_is_rp,    _function_action_rp);
 
-       SCF_DFA_MODULE_NODE(dfa, function, lp,     scf_dfa_is_lp,    _function_action_lp);
-       SCF_DFA_MODULE_NODE(dfa, function, rp,     scf_dfa_is_rp,    _function_action_rp);
+       SCF_DFA_MODULE_NODE(dfa, function, pf_star,  scf_dfa_is_star,  _function_action_pf_star);
+       SCF_DFA_MODULE_NODE(dfa, function, pf_lp,    scf_dfa_is_lp,    _function_action_pf_lp);
+       SCF_DFA_MODULE_NODE(dfa, function, pf_rp,    scf_dfa_is_rp,    _function_action_pf_rp);
 
        scf_parse_t*     parse = dfa->priv;
        dfa_data_t*      d     = parse->dfa_data;
@@ -437,6 +556,10 @@ static int _dfa_init_syntax_function(scf_dfa_t* dfa)
        SCF_DFA_GET_MODULE_NODE(dfa, function, lp,        lp);
        SCF_DFA_GET_MODULE_NODE(dfa, function, rp,        rp);
 
+       SCF_DFA_GET_MODULE_NODE(dfa, function, pf_star,   pf_star);
+       SCF_DFA_GET_MODULE_NODE(dfa, function, pf_lp,     pf_lp);
+       SCF_DFA_GET_MODULE_NODE(dfa, function, pf_rp,     pf_rp);
+
        SCF_DFA_GET_MODULE_NODE(dfa, type,     _const,    _const);
        SCF_DFA_GET_MODULE_NODE(dfa, type,     base_type, base_type);
        SCF_DFA_GET_MODULE_NODE(dfa, identity, identity,  type_name);
@@ -445,6 +568,21 @@ static int _dfa_init_syntax_function(scf_dfa_t* dfa)
        SCF_DFA_GET_MODULE_NODE(dfa, type,     identity,  identity);
        SCF_DFA_GET_MODULE_NODE(dfa, block,    entry,     block);
 
+       // function pointer
+       scf_dfa_node_add_child(base_type, pf_lp);
+       scf_dfa_node_add_child(type_name, pf_lp);
+       scf_dfa_node_add_child(star,      pf_lp);
+
+       scf_dfa_node_add_child(pf_lp,     pf_star);
+       scf_dfa_node_add_child(pf_star,   identity);
+       scf_dfa_node_add_child(identity,  pf_rp);
+
+       scf_dfa_node_add_child(pf_star,   pf_star);
+       scf_dfa_node_add_child(pf_lp,     pf_lp);
+       scf_dfa_node_add_child(pf_rp,     pf_rp);
+
+       scf_dfa_node_add_child(pf_rp,     lp);
+
        // function start
        scf_dfa_node_add_child(identity,  lp);
 
index 66ba0eac8157296d25e817b9b86b41cc16d0309b..61e5cd29fec22121fcf022dd5e72850bca70b3d1 100644 (file)
 
 extern scf_dfa_module_t dfa_module_macro;
 
-static inline int _macro_action_if(scf_dfa_t* dfa, scf_vector_t* words, void* data)
-{
-       scf_lex_word_t* w  = words->data[words->size - 1];
-       scf_lex_word_t* w1 = dfa->ops->pop_word(dfa);
-       scf_lex_word_t* w2;
-       scf_lex_word_t* w3;
-
-       if (!w1)
-               return SCF_DFA_ERROR;
 
-       if (!scf_lex_is_const_integer(w1)) {
-               scf_loge("the condition after '#if' must be a const integer, file: %s, line: %d\n", w->file->data, w->line);
-               return SCF_DFA_ERROR;
+static int __macro_do_if_else(scf_lex_t* lex, scf_lex_word_t* w, int flag)
+{
+       scf_lex_word_t*  h  = NULL;
+       scf_lex_word_t*  w1 = NULL;
+       scf_lex_word_t*  w2 = NULL;
+
+       int ret = __macro_drop_to_LF(lex);
+       if (ret < 0) {
+               scf_loge("'#endif' NOT found for '#%s' in file: %s, line: %d\n", w->text->data, w->file->data, w->line);
+               return ret;
        }
 
-       int flag = w1->data.u32;
-
-       scf_lex_word_free(w1);
-       w1 = NULL;
-
-       while (1) {
-               w1 = dfa->ops->pop_word(dfa);
-               if (!w1)
-                       return SCF_DFA_ERROR;
-
-               int type = w1->type;
+       if (!flag) {
+               ret = __macro_drop_to(lex, &w1, &w2);
+               if (ret < 0)
+                       return ret;
 
-               scf_lex_word_free(w1);
-               w1 = NULL;
+               if (SCF_LEX_WORD_KEY_ENDIF == w2->type) {
+                       scf_lex_word_free(w2);
+                       scf_lex_word_free(w1);
 
-               if (SCF_LEX_WORD_EOF == type) {
-                       scf_loge("'#endif' NOT found for '#if' in file: %s, line: %d\n", w->file->data, w->line);
-                       return SCF_DFA_ERROR;
+                       return __macro_drop_to_LF(lex);
                }
 
-               if (SCF_LEX_WORD_LF == type)
-                       break;
+               scf_lex_push_word(lex, w2);
+               scf_lex_push_word(lex, w1);
+               return SCF_DFA_OK;
        }
 
-       scf_lex_word_t* h = NULL;
+       ret = __macro_pop_to(lex, &h, &w1, &w2);
+       if (ret < 0) {
+               scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free);
+               return ret;
+       }
 
-       int n_if = 1;
+       int type = w2->type;
 
-       while (1) {
-               w1 = dfa->ops->pop_word(dfa);
-               if (!w1)
-                       goto error;
-               w1->next = NULL;
+       scf_lex_word_free(w2);
+       scf_lex_word_free(w1);
+       w1 = NULL;
+       w2 = NULL;
 
-               if (SCF_LEX_WORD_EOF == w1->type) {
-                       scf_loge("'#endif' NOT found for '#if' in file: %s, line: %d\n", w->file->data, w->line);
-                       scf_lex_word_free(w1);
-                       goto error;
-               }
+       while (SCF_LEX_WORD_KEY_ENDIF != type) {
 
-               if (SCF_LEX_WORD_HASH == w1->type) {
-                       w2 = dfa->ops->pop_word(dfa);
-                       if (!w2) {
-                               scf_lex_word_free(w1);
-                               goto error;
-                       }
-                       w2->next = NULL;
-
-                       scf_logd("'#%s' file: %s, line: %d\n", w2->text->data, w2->file->data, w2->line);
-
-                       if (SCF_LEX_WORD_EOF == w2->type) {
-                               scf_loge("'#endif' NOT found for '#if' in file: %s, line: %d\n", w->file->data, w->line);
-                               scf_lex_word_free(w2);
-                               scf_lex_word_free(w1);
-                               goto error;
-                       }
-
-                       if (n_if < 1) {
-                               scf_loge("extra '#%s' without an '#if' in file: %s, line: %d\n", w2->text->data, w2->file->data, w2->line);
-                               scf_lex_word_free(w2);
-                               scf_lex_word_free(w1);
-                               goto error;
-                       }
-
-                       if (SCF_LEX_WORD_KEY_ELSE == w2->type || SCF_LEX_WORD_KEY_ENDIF == w2->type) {
-                               w3 = dfa->ops->pop_word(dfa);
-                               if (!w3) {
-                                       scf_lex_word_free(w2);
-                                       scf_lex_word_free(w1);
-                                       goto error;
-                               }
-                               w3->next = NULL;
-
-                               if (SCF_LEX_WORD_LF != w3->type) {
-                                       scf_loge("'\\n' NOT found after '#%s' in file: %s, line: %d\n", w2->text->data, w2->file->data, w2->line);
-                                       scf_lex_word_free(w3);
-                                       scf_lex_word_free(w2);
-                                       scf_lex_word_free(w1);
-                                       goto error;
-                               }
-
-                               if (SCF_LEX_WORD_KEY_ELSE == w2->type) {
-                                       if (1 == n_if) {
-                                               flag = !flag;
-                                               scf_lex_word_free(w3);
-                                               scf_lex_word_free(w2);
-                                               scf_lex_word_free(w1);
-                                               continue;
-                                       }
-                               } else {
-                                       if (0 == --n_if) {
-                                               scf_lex_word_free(w3);
-                                               scf_lex_word_free(w2);
-                                               scf_lex_word_free(w1);
-                                               break;
-                                       }
-                               }
-
-                               if (flag)
-                                       w2->next = w3;
-                               else
-                                       scf_lex_word_free(w3);
-                               w3 = NULL;
-
-                       } else if (SCF_LEX_WORD_KEY_IF == w2->type) {
-                               n_if++;
-                       }
-
-                       if (flag)
-                               w1->next = w2;
-                       else
-                               scf_lex_word_free(w2);
-                       w2 = NULL;
+               ret = __macro_drop_to(lex, &w1, &w2);
+               if (ret < 0) {
+                       scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free);
+                       return ret;
                }
 
-               if (flag) {
-                       while (w1) {
-                               w2 = w1->next;
-                               w1->next = h;
-                               h  = w1;
-                               w1 = w2;
-                       }
-               } else
-                       scf_lex_word_free(w1);
+               type = w2->type;
+
+               scf_lex_word_free(w2);
+               scf_lex_word_free(w1);
                w1 = NULL;
+               w2 = NULL;
+       }
+
+       ret = __macro_drop_to_LF(lex);
+       if (ret < 0) {
+               scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free);
+               return ret;
        }
 
        while (h) {
-               w = h;
-               scf_logd("'%s' file: %s, line: %d\n", w->text->data, w->file->data, w->line);
-               h = w->next;
-               dfa->ops->push_word(dfa, w);
+               w1 = h;
+               h  = h->next;
+
+               scf_lex_push_word(lex, w1);
        }
 
        return SCF_DFA_OK;
+}
 
-error:
-       while (h) {
-               w = h;
-               h = w->next;
-               scf_lex_word_free(w);
-       }
-       return SCF_DFA_ERROR;
+static int _macro_action_if(scf_dfa_t* dfa, scf_vector_t* words, void* data)
+{
+       scf_parse_t*     parse = dfa->priv;
+       dfa_data_t*      d     = data;
+       scf_lex_word_t*  w     = words->data[words->size - 1];
+
+       int flag = __macro_if_expr(parse->lex);
+       if (flag < 0)
+               return flag;
+
+       return __macro_do_if_else(parse->lex, w, flag);
+}
+
+static int _macro_action_else(scf_dfa_t* dfa, scf_vector_t* words, void* data)
+{
+       scf_parse_t*     parse = dfa->priv;
+       scf_lex_word_t*  w     = words->data[words->size - 1];
+
+       return __macro_do_if_else(parse->lex, w, 1);
 }
 
 static int _dfa_init_module_macro(scf_dfa_t* dfa)
 {
-       SCF_DFA_MODULE_NODE(dfa, macro, hash, scf_dfa_is_hash, scf_dfa_action_next);
-       SCF_DFA_MODULE_NODE(dfa, macro, _if,  scf_dfa_is_if,   _macro_action_if);
+       SCF_DFA_MODULE_NODE(dfa, macro, hash,   scf_dfa_is_hash,  scf_dfa_action_next);
+       SCF_DFA_MODULE_NODE(dfa, macro, _if,    scf_dfa_is_if,    _macro_action_if);
+       SCF_DFA_MODULE_NODE(dfa, macro, _elif,  scf_dfa_is_elif,  _macro_action_if);
+       SCF_DFA_MODULE_NODE(dfa, macro, _else,  scf_dfa_is_else,  _macro_action_else);
 
        return SCF_DFA_OK;
 }
 
 static int _dfa_init_syntax_macro(scf_dfa_t* dfa)
 {
-       SCF_DFA_GET_MODULE_NODE(dfa,  macro, hash, hash);
-       SCF_DFA_GET_MODULE_NODE(dfa,  macro, _if,  _if);
+       SCF_DFA_GET_MODULE_NODE(dfa,  macro, hash,   hash);
+       SCF_DFA_GET_MODULE_NODE(dfa,  macro, _if,    _if);
+       SCF_DFA_GET_MODULE_NODE(dfa,  macro, _elif,  _elif);
+       SCF_DFA_GET_MODULE_NODE(dfa,  macro, _else,  _else);
 
        scf_vector_add(dfa->syntaxes, hash);
 
        scf_dfa_node_add_child(hash,  _if);
+       scf_dfa_node_add_child(hash,  _elif);
+       scf_dfa_node_add_child(hash,  _else);
        return 0;
 }
 
index d007d156cc40997b02f4ca7b281544279e3b92a2..ece42609c3eebdec9953545fbbec2e15e797543a 100644 (file)
@@ -256,6 +256,13 @@ static inline int scf_dfa_is_if(scf_dfa_t* dfa, void* word)
        return SCF_LEX_WORD_KEY_IF == w->type;
 }
 
+static inline int scf_dfa_is_elif(scf_dfa_t* dfa, void* word)
+{
+       scf_lex_word_t* w = word;
+
+       return SCF_LEX_WORD_KEY_ELIF == w->type;
+}
+
 static inline int scf_dfa_is_else(scf_dfa_t* dfa, void* word)
 {
        scf_lex_word_t* w = word;
index 62faa07509906d3865ad87dadd8d110553de4bb9..2976c51186009d9976c1221c94be1587706b221d 100644 (file)
@@ -706,24 +706,32 @@ scf_operator_handler_pt  scf_find_expr_operator_handler(const int type)
 
 int scf_expr_calculate(scf_ast_t* ast, scf_expr_t* e, scf_variable_t** pret)
 {
-       if (!e || !e->nodes || e->nb_nodes <= 0)
-               return -1;
-
-       if (scf_expr_semantic_analysis(ast, e) < 0)
-               return -1;
+       if (!e)
+               return -EINVAL;
 
-       scf_handler_data_t d = {0};
-       scf_variable_t*    v;
+       scf_handler_data_t  d = {0};
+       scf_variable_t*     v;
+       scf_node_t*         node = e;
 
-       if (!scf_type_is_var(e->nodes[0]->type)) {
+       if (SCF_OP_EXPR == e->type) {
 
-               if (_scf_expr_calculate_internal(ast, e->nodes[0], &d) < 0) {
+               if (!e->nodes || e->nb_nodes != 1) {
                        scf_loge("\n");
-                       return -1;
+                       return -EINVAL;
                }
+
+               node = e->nodes[0];
        }
 
-       v = _scf_operand_get(e->nodes[0]);
+       int ret = scf_expr_semantic_analysis(ast, node);
+       if (ret < 0)
+               return ret;
+
+       ret = _scf_expr_calculate_internal(ast, node, &d);
+       if (ret < 0)
+               return ret;
+
+       v = _scf_operand_get(node);
 
        if (pret)
                *pret = scf_variable_ref(v);
index 6ba2ae3fb0bad0826d3179efdd483507acf07c22..7769eb9e394caf18180cdcd6db62a169ceb5c184 100644 (file)
@@ -3177,17 +3177,22 @@ int scf_expr_semantic_analysis(scf_ast_t* ast, scf_expr_t* e)
 {
        scf_handler_data_t d = {0};
 
-       if (!e->nodes || e->nb_nodes != 1) {
-               scf_loge("\n");
-               return -1;
-       }
+       scf_node_t* node = e;
 
-       int ret = _scf_expr_calculate_internal(ast, e->nodes[0], &d);
-       if (ret < 0) {
-               scf_loge("\n");
-               return -1;
+       if (SCF_OP_EXPR == e->type) {
+
+               if (!e->nodes || e->nb_nodes != 1) {
+                       scf_loge("\n");
+                       return -EINVAL;
+               }
+
+               node = e->nodes[0];
        }
 
+       int ret = _scf_expr_calculate_internal(ast, node, &d);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
index 76d512067791f7a6967ccaeb8d0ae8bc7d6e7b87..00b910fb1e5f1c0d20bfddd174dfe976a4b35624 100644 (file)
@@ -1797,7 +1797,7 @@ int scf_parse_compile_functions(scf_parse_t* parse, scf_vector_t* functions)
                }
 
                assert(scf_list_empty(&h));
-//             scf_basic_block_print_list(&f->basic_block_list_head);
+               scf_basic_block_print_list(&f->basic_block_list_head);
        }
 
        int ret = scf_optimize(parse->ast, functions);
index a1afd013dc1d71d49b1939c67f34d3139327dc1e..bd33b0f0e486590e84946175cf360cf925e7ca48 100644 (file)
@@ -1,6 +1,6 @@
 #include"scf_string.h"
 
-#define SCF_STRING_NUMBER_INC  4
+#define SCF_STRING_NUMBER_INC  7
 
 scf_string_t* scf_string_alloc()
 {
index dcf1af4627f3dfe4895200c98649b7d1a0985564..9e433a44c9a6f15a48d3f9934cca7bb701b5cda3 100644 (file)
@@ -4,12 +4,11 @@
 #include"scf_vector.h"
 
 typedef struct {
-       intptr_t capacity;
        size_t   len;
+       intptr_t capacity;
        uint8_t* data;
 } scf_string_t;
 
-
 scf_string_t*  scf_string_alloc();
 
 scf_string_t*  scf_string_clone(const scf_string_t* s);
index 78f1de445644ee17b075cac07a37f8125c12c94f..a747bd6081f04cafdf63c9056d65e5349da9ee36 100644 (file)
@@ -64,6 +64,7 @@ static inline int scf_vector_extend(scf_vector_t* v, int size)
                v->capacity = size;
        }
 
+       v->size = size;
        return 0;
 }