SCF_LEX_N_OPS, // number of operators
SCF_LEX_WORD_RANGE, // .. range
- SCF_LEX_WORD_VAR_ARGS, // ... variable args
+ SCF_LEX_WORD_VA_ARGS, // ... variable args
SCF_LEX_WORD_LB, // { left brace
SCF_LEX_WORD_RB, // } right brace
SCF_LEX_WORD_KEY_OPERATOR, // operator
SCF_LEX_WORD_KEY_UNDERLINE, // _ underline
+ // macro key word
SCF_LEX_WORD_KEY_INCLUDE, // #include
SCF_LEX_WORD_KEY_DEFINE, // #define
SCF_LEX_WORD_KEY_UNDEF, // #undef
+ SCF_LEX_WORD_KEY_ERROR, // #error
+ SCF_LEX_WORD_KEY_LINE, // #line
+ SCF_LEX_WORD_KEY_PRAGMA, // #pragma
+
SCF_LEX_WORD_KEY_IFDEF, // #ifdef
SCF_LEX_WORD_KEY_IFNDEF, // #ifndef
SCF_LEX_WORD_KEY_ELIF, // #elif
int refs;
uint8_t def_flag:1;
+ uint8_t vargs_flag:1;
scf_lex_word_t* w;
scf_vector_t* argv;
--- /dev/null
+#define A
+
+#if defined(A)
+int printf(const char* fmt, ...);
+#endif
+
+int main()
+{
+ int define = 5;
+
+ printf("define: %d\n", define);
+ return 0;
+}
--- /dev/null
+#pragma A
+
+#define P
+
+#ifdef P
+int printf(const char* fmt, ...);
+#else
+#error "printf() NOT include!"
+#endif
+
+int main()
+{
+ printf("macro '#error' test ok\n");
+ return 0;
+}
-#if 1 ? 2 < 3 ? 0 : 4 : 5
+#if 1 ? 3 < 3 ? 0 : 4 : 5
int printf(const char* fmt, ...);
#else
#endif
-#define A(x) #x
+#define A(x, y) #x, (y)
int printf(const char* fmt, ...);
int main()
{
- printf("%s\n", A(zzz));
+ printf("%s, %d\n", A(zzz, 1));
return 0;
}
--- /dev/null
+int printf(const char* fmt, ...);
+
+#define logi(fmt, ...) printf("%s(), %d, info: "fmt, __func__, __LINE__, ##__VA_ARGS__)
+
+int main()
+{
+ logi("hello, %d, %lg\n", 1, 3.14);
+ return 0;
+}
#include"scf_lex.h"
-static scf_key_word_t key_words[] =
+static scf_key_word_t macro_key_words[] =
{
- {SCF_CSTR("if"), SCF_LEX_WORD_KEY_IF},
- {SCF_CSTR("else"), SCF_LEX_WORD_KEY_ELSE},
-
{SCF_CSTR("include"), SCF_LEX_WORD_KEY_INCLUDE},
{SCF_CSTR("define"), SCF_LEX_WORD_KEY_DEFINE},
- {SCF_CSTR("defined"), SCF_LEX_WORD_KEY_DEFINED},
- {SCF_CSTR("undef"), SCF_LEX_WORD_KEY_UNDEF},
- {SCF_CSTR("ifdef"), SCF_LEX_WORD_KEY_IFDEF},
{SCF_CSTR("ifndef"), SCF_LEX_WORD_KEY_IFNDEF},
+ {SCF_CSTR("ifdef"), SCF_LEX_WORD_KEY_IFDEF},
+
+ {SCF_CSTR("if"), SCF_LEX_WORD_KEY_IF},
+ {SCF_CSTR("else"), SCF_LEX_WORD_KEY_ELSE},
{SCF_CSTR("elif"), SCF_LEX_WORD_KEY_ELIF},
{SCF_CSTR("endif"), SCF_LEX_WORD_KEY_ENDIF},
+ {SCF_CSTR("undef"), SCF_LEX_WORD_KEY_UNDEF},
+
+ {SCF_CSTR("pragma"), SCF_LEX_WORD_KEY_PRAGMA},
+ {SCF_CSTR("line"), SCF_LEX_WORD_KEY_LINE},
+ {SCF_CSTR("error"), SCF_LEX_WORD_KEY_ERROR},
+};
+
+static scf_key_word_t key_words[] =
+{
+ {SCF_CSTR("if"), SCF_LEX_WORD_KEY_IF},
+ {SCF_CSTR("else"), SCF_LEX_WORD_KEY_ELSE},
+
{SCF_CSTR("for"), SCF_LEX_WORD_KEY_FOR},
{SCF_CSTR("while"), SCF_LEX_WORD_KEY_WHILE},
{SCF_CSTR("do"), SCF_LEX_WORD_KEY_DO},
{'0', '\0'},
};
-int _find_key_word(const scf_string_t* text)
+static int __find_key_word(const scf_string_t* text, const scf_key_word_t* key_words, int n)
{
- scf_key_word_t* key;
+ const scf_key_word_t* key;
int i;
- for (i = 0; i < sizeof(key_words) / sizeof(key_words[0]); i++) {
- key = &key_words[i];
+ for (i = 0; i < n; i++) {
+ key = &key_words[i];
if (text->len == key->len && !memcmp(text->data, key->text, key->len))
return key->type;
return -1;
}
+int _find_key_word(const scf_string_t* text)
+{
+ return __find_key_word(text, key_words, sizeof(key_words) / sizeof(key_words[0]));
+}
+
+static int _find_macro_key_word(const scf_string_t* text)
+{
+ return __find_key_word(text, macro_key_words, sizeof(macro_key_words) / sizeof(macro_key_words[0]));
+}
+
static int _find_escape_char(const int c)
{
int i;
}
}
-static int _lex_macro(scf_lex_t* lex)
+static int _lex_macro_LF(scf_lex_t* lex)
{
scf_char_t* h = NULL;
scf_char_t** pp = &h;
if ('#' == c->c) {
w->type = SCF_LEX_WORD_HASH2;
- w->text = scf_string_cstr("##");
+ w->text = scf_string_cstr_len("##", 2);
lex->pos += 2;
free(c);
} else {
- w->text = scf_string_cstr("#");
+ w->text = scf_string_cstr_len("#", 1);
lex->pos++;
_lex_push_char(lex, c);
}
c = NULL;
+
+ int ret = _lex_macro_LF(lex);
+ if (ret < 0) {
+ scf_lex_word_free(w);
+ return ret;
+ }
+
+ if (SCF_LEX_WORD_HASH == w->type) {
+ scf_lex_word_t* key = NULL;
+
+ ret = __lex_pop_word(lex, &key);
+ if (ret < 0) {
+ scf_lex_word_free(w);
+ return ret;
+ }
+
+ if (SCF_LEX_WORD_ID == key->type) {
+
+ int type = _find_macro_key_word(key->text);
+ if (type >= 0)
+ key->type = type;
+ }
+
+ scf_lex_push_word(lex, key);
+ key = NULL;
+ }
+
*pword = w;
- return _lex_macro(lex);
+ return 0;
}
if ('$' == c->c && lex->asm_flag)
ret = __parse_macro_define(lex, 0);
break;
+ case SCF_LEX_WORD_KEY_PRAGMA:
+ case SCF_LEX_WORD_KEY_LINE:
+ ret = __macro_drop_to_LF(lex);
+ break;
+
+ case SCF_LEX_WORD_KEY_ERROR:
+ scf_loge("#error ");
+ __macro_print_to_LF(lex);
+ ret = -EINVAL;
+ break;
+
default:
if (lex->asm_flag) {
scf_lex_push_word(lex, w1);
uint8_t asm_flag:1;
};
+int _find_key_word(const scf_string_t* text);
scf_char_t* _lex_pop_char (scf_lex_t* lex);
void _lex_push_char(scf_lex_t* lex, scf_char_t* c);
int __macro_pop_to (scf_lex_t* lex, scf_lex_word_t** h, scf_lex_word_t** pw1, scf_lex_word_t** pw2);
int __macro_drop_to(scf_lex_t* lex, scf_lex_word_t** pw1, scf_lex_word_t** pw2);
-int __macro_drop_to_LF(scf_lex_t* lex);
+
+int __macro_drop_to_LF (scf_lex_t* lex);
+int __macro_print_to_LF(scf_lex_t* lex);
int __parse_macro_define(scf_lex_t* lex, int def_flag);
int __parse_macro_ifdef (scf_lex_t* lex, int def_flag);
#include"scf_lex.h"
-int _find_key_word(const char* text);
-
static scf_key_word_t number_postfix[] =
{
{SCF_CSTR("l"), SCF_LEX_WORD_CONST_INT},
free(c2);
c2 = NULL;
- w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_VAR_ARGS);
+ w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_VA_ARGS);
w->text = s;
s = NULL;
} else {
_lex_push_char(lex, c1);
c1 = NULL;
- int type = _find_key_word(s->data);
+ int type = _find_key_word(s);
if (type < 0) {
scf_loge("unknown asm key word '%s', file: %s, line: %d\n", s->data, lex->file->data, lex->nb_lines);
return NULL;
}
+int __macro_print_to_LF(scf_lex_t* lex)
+{
+ scf_lex_word_t* w = NULL;
+ int type;
+
+ do {
+ int ret = __lex_pop_word(lex, &w);
+ if (ret < 0)
+ return ret;
+
+ type = w->type;
+
+ if (SCF_LEX_WORD_LF != type) {
+
+ printf("%s ", w->text->data);
+ }
+
+ scf_lex_word_free(w);
+ w = NULL;
+
+ if (SCF_LEX_WORD_EOF == type)
+ return -EINVAL;
+
+ } while (SCF_LEX_WORD_LF != type);
+
+ printf("\n");
+ return 0;
+}
+
int __macro_drop_to_LF(scf_lex_t* lex)
{
scf_lex_word_t* w = NULL;
}
}
- if (!scf_lex_is_identity(w)) {
+ if (SCF_LEX_WORD_ID != w->type && SCF_LEX_WORD_VA_ARGS != w->type) {
+
scf_loge("macro arg '%s' should be an identity, file: %s, line: %d\n", w->text->data, w->file->data, w->line);
scf_lex_word_free(w);
return -EINVAL;
scf_logw("macro '%s' arg: %s\n", m->w->text->data, w->text->data);
- ret = scf_vector_add(m->argv, w);
- if (ret < 0) {
+ if (m->vargs_flag) {
+ scf_loge("macro has arg '%s' after '...' which must be the last arg, file: %s, line: %d\n", w->text->data, w->file->data, w->line);
scf_lex_word_free(w);
- return ret;
+ return -EINVAL;
+ }
+
+ if (SCF_LEX_WORD_VA_ARGS == w->type) {
+ m->vargs_flag = 1;
+ scf_lex_word_free(w);
+ } else {
+ ret = scf_vector_add(m->argv, w);
+ if (ret < 0) {
+ scf_lex_word_free(w);
+ return ret;
+ }
}
w = NULL;
goto error;
}
- scf_lex_word_free(w);
- w = NULL;
+ w->next = NULL;
+
+ *pp = w;
+ pp = &w->next;
if (n_rps == n_lps)
pp = NULL;
w = NULL;
}
- if (m->argv->size != argv->size) {
+ if (m->argv->size > argv->size
+ || (m->argv->size < argv->size && !m->vargs_flag)) {
+
scf_loge("macro '%s' needs %d args, but in fact give %d args, file: %s, line: %d\n",
m->w->text->data, m->argv->size, argv->size, use->file->data, use->line);
ret = -1;
scf_lex_word_t* w;
scf_string_t* s;
+ if (SCF_LEX_WORD_COMMA == h->type && !h->next)
+ return 0;
+
if (h->type != SCF_LEX_WORD_CONST_STRING) {
h->type = SCF_LEX_WORD_CONST_STRING;
while ( h->next) {
w = h->next;
+ if (SCF_LEX_WORD_COMMA == w->type && !w->next)
+ break;
+
if (SCF_LEX_WORD_CONST_STRING != w->type)
s = w->text;
else
continue;
}
- scf_logd("p: '%s', line: %d, hash: %d\n", p->text->data, p->line, hash);
+ scf_logd("p: '%s', line: %d:%d, hash: %d\n", p->text->data, p->line, p->pos, hash);
if (m->argv) {
assert(argv);
break;
}
+ int j = 0;
+ int n = 0;
+
if (i < m->argv->size) {
+ j = i;
+ n = i + 1;
+
+ } else if (m->vargs_flag && !strcmp(p->text->data, "__VA_ARGS__")) {
+ j = i;
+ n = argv->size;
+ }
+
+ if (j < n) {
scf_lex_word_t** tmp = pp;
- for (w = argv->data[i]; w; w = w->next) {
+ do {
+ for (w = argv->data[j]; w; w = w->next) {
- *pp = scf_lex_word_clone(w);
- if (!*pp) {
- ret = -ENOMEM;
- goto error;
- }
+ if (j < m->argv->size
+ && SCF_LEX_WORD_COMMA == w->type
+ && !w->next)
+ break;
- if (!strcmp((*pp)->text->data, "__LINE__"))
- (*pp)->data.u64 = use->line;
+ *pp = scf_lex_word_clone(w);
+ if (!*pp) {
+ ret = -ENOMEM;
+ goto error;
+ }
- pp = &(*pp)->next;
- }
+ if (!strcmp((*pp)->text->data, "__LINE__"))
+ (*pp)->data.u64 = use->line;
+
+ scf_logd("\033[32m p: '%s', line: %d:%d, hash: %d\033[0m\n", (*pp)->text->data, (*pp)->line, (*pp)->pos, hash);
+
+ pp = &(*pp)->next;
+ }
+ } while (++j < n);
if (1 == hash) {
ret = __convert_str(*tmp);
return ret;
}
+ w = h;
+ while (w) {
+ scf_lex_word_t* w2;
+ scf_lex_word_t* w1 = w->next;
+
+ if (!w1)
+ break;
+
+ if (SCF_LEX_WORD_CONST_STRING == w1->type) {
+
+ if (SCF_LEX_WORD_CONST_STRING == w->type) {
+
+ if ((ret = scf_string_cat(w->text, w1->text)) < 0
+ || (ret = scf_string_cat(w->data.s, w1->data.s)) < 0) {
+
+ scf_slist_clear(h, scf_lex_word_t, next, scf_lex_word_free);
+ return ret;
+ }
+
+ w->next = w1->next;
+
+ scf_lex_word_free(w1);
+ w1 = NULL;
+ continue;
+ }
+
+ } else if (SCF_LEX_WORD_COMMA == w1->type) {
+ w2 = w1->next;
+
+ if (w2 && SCF_LEX_WORD_HASH2 == w2->type) {
+ w1->next = w2->next;
+
+ scf_lex_word_free(w2);
+ w2 = w1->next;
+
+ if (w2 && SCF_LEX_WORD_ID == w2->type && !strcmp(w2->text->data, "__VA_ARGS__")) {
+
+ w->next = w2->next;
+
+ scf_lex_word_free(w1);
+ scf_lex_word_free(w2);
+ w1 = NULL;
+ w2 = NULL;
+ }
+ }
+ }
+
+ w = w->next;
+ }
+
#if 0
w = h;
while (w) {
w = w->next;
}
#endif
+
*pp = lex->word_list;
lex->word_list = h;
return 0;
if (ret < 0)
return ret;
+ if (SCF_LEX_WORD_ID == w0->type && !strcmp(w0->text->data, "defined"))
+ w0->type = SCF_LEX_WORD_KEY_DEFINED;
+
switch (w0->type)
{
case SCF_LEX_WORD_PLUS:
*ctx->pp = op2;
ctx->pp = &op2->next;
+
+ ctx->n_rps++;
return 0;
}
static int __macro_operator_defined(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand)
{
scf_lex_word_t* w0 = NULL;
+ int ret;
- int ret = __lex_pop_word(lex, &w0);
- if (ret < 0)
- return ret;
+ int n_lps = 0;
+ int n_rps = 0;
+
+ while (1) {
+ ret = __lex_pop_word(lex, &w0);
+ if (ret < 0)
+ return ret;
+
+ w0->next = NULL;
+ *ctx->pp = w0;
+ ctx->pp = &w0->next;
- if (SCF_LEX_WORD_ID != w0->type) {
- scf_loge("'%s' after 'defined' in #if is NOT an macro identity, file: %s, line: %d\n",
- w0->text->data, w0->file->data, w0->line);
+ if (SCF_LEX_WORD_ID == w0->type)
+ break;
+
+ if (SCF_LEX_WORD_LP != w0->type) {
+
+ scf_loge("'%s' after 'defined' in #if is NOT an macro identity, file: %s, line: %d\n",
+ w0->text->data, w0->file->data, w0->line);
+ return -EINVAL;
+ }
- ret = -EINVAL;
- goto error;
+ n_lps++;
+ w0 = NULL;
}
+ assert(SCF_LEX_WORD_ID == w0->type);
+
if (__find_macro(lex, w0))
w0->data.i64 = 1;
else
scf_logi("w0: %s, result: %ld\n", w0->text->data, w0->data.i64);
- ret = 0;
+ w0 = NULL;
-error:
- w0->next = NULL;
- *ctx->pp = w0;
- ctx->pp = &w0->next;
- return ret;
+ while (n_rps < n_lps) {
+
+ ret = __lex_pop_word(lex, &w0);
+ if (ret < 0)
+ return ret;
+
+ w0->next = NULL;
+ *ctx->pp = w0;
+ ctx->pp = &w0->next;
+
+ if (SCF_LEX_WORD_RP != w0->type) {
+
+ scf_loge("too less ')' before '%s' in #if, file: %s, line: %d\n",
+ w0->text->data, w0->file->data, w0->line);
+ return -EINVAL;
+ }
+
+ n_rps++;
+ w0 = NULL;
+ }
+
+ return 0;
}
#define MACRO_OPERATOR_UNARY(name, op) \
static int __macro_operator_rp(scf_lex_t* lex, scf_macro_ctx_t* ctx, scf_lex_word_t* w_op, int n_consts, scf_lex_word_t** operand)
{
+ if (++ctx->n_rps > ctx->n_lps) {
+
+ scf_loge("too many '%s', file: %s, line: %d, pos: %d\n",
+ w_op->text->data, w_op->file->data, w_op->line, w_op->pos);
+ return -EINVAL;
+ }
+
return 0;
}
*ctx->pp = op2;
ctx->pp = &op2->next;
+ ctx->n_lps++;
+
scf_macro_operator_pt f;
switch (op2->type)
{
case SCF_LEX_WORD_RP:
+ ctx->n_rps++;
break;
case SCF_LEX_WORD_STAR:
return -EINVAL;
}
+ if (SCF_LEX_WORD_ID == w->type && !strcmp(w->text->data, "defined"))
+ w->type = SCF_LEX_WORD_KEY_DEFINED;
+
if (scf_lex_is_operator(w)) {
w->next = NULL;
goto error;
}
+ if (SCF_LEX_WORD_ID == w->type && !strcmp(w->text->data, "defined"))
+ w->type = SCF_LEX_WORD_KEY_DEFINED;
+
if (scf_lex_is_operator(w)) {
scf_macro_operator_pt f = macro_operators[w->type];
if (!f) {
goto error;
}
+ if (operand) {
+ scf_loge("NO binary operator before operand '%s', file: %s, line: %d\n",
+ w->text->data, w->file->data, w->line);
+
+ ret = -EINVAL;
+ goto error;
+ }
+
scf_logi("w: %s, w->data.u64: %ld\n", w->text->data, w->data.u64);
operand = w;
{
scf_lex_word_t* w = word;
- return SCF_LEX_WORD_VAR_ARGS == w->type;
+ return SCF_LEX_WORD_VA_ARGS == w->type;
}
static inline int scf_dfa_is_const(scf_dfa_t* dfa, void* word)