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, // +=
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
SCF_LEX_WORD_COMMA, // , comma
SCF_LEX_WORD_SEMICOLON, // ;
- SCF_LEX_WORD_COLON, // : colon
SCF_LEX_WORD_SPACE, // ' ' space
// eof
--- /dev/null
+int printf(const char* fmt, ...);
+
+int (*pf)(const char* fmt, ...);
+
+int main()
+{
+ pf = printf;
+
+ pf("hello world\n");
+ return 0;
+}
--- /dev/null
+#if 1 ? 2 < 3 ? 0 : 4 : 5
+int printf(const char* fmt, ...);
+#else
+#endif
+
+int main()
+{
+ printf("hello world\n");
+ return 0;
+}
--- /dev/null
+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;
+}
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
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[] =
{'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;
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);
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;
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;
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);
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);
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);
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)
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;
}
#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;
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;
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;
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;
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;
}
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();
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);
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;
--- /dev/null
+#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;
+}
return -EINVAL;
}
- scf_x64_context_t* x64 = ctx->priv;
- scf_function_t* f = x64->f;
- scf_3ac_operand_t* src0 = 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;
}
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);
}
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);
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);
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) {
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;
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
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)
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;
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;
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;
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;
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);
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);
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;
}
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;
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);
{
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;
}
}
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);
#include"scf_string.h"
-#define SCF_STRING_NUMBER_INC 4
+#define SCF_STRING_NUMBER_INC 7
scf_string_t* scf_string_alloc()
{
#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);
v->capacity = size;
}
+ v->size = size;
return 0;
}