// data types
SCF_LEX_WORD_KEY_CHAR, // char
+ SCF_LEX_WORD_KEY_SHORT, // short
SCF_LEX_WORD_KEY_INT, // int
+ SCF_LEX_WORD_KEY_LONG, // long
+
+ SCF_LEX_WORD_KEY_SIGNED, // signed
+ SCF_LEX_WORD_KEY_UNSIGNED, // unsigned
+
SCF_LEX_WORD_KEY_FLOAT, // float
SCF_LEX_WORD_KEY_DOUBLE, // double
--- /dev/null
+int printf(const char* fmt, ...);
+
+int main()
+{
+ int restrict = 1;
+
+ printf("restrict: %d\n", restrict);
+ return 0;
+}
-#include"hello.h"
+#include"stdio.h"
int main()
{
+++ /dev/null
-#ifndef HELLO_H
-#define HELLO_H
-int printf(const char* fmt, ...);
-#endif
--- /dev/null
+int printf(const char* fmt, ...);
+
+int main()
+{
+ short int si = 3;
+ long int li = 4;
+
+ long long ll = 5;
+
+ unsigned long ul = 6;
+
+ signed s = 7;
+ unsigned u = 8;
+
+ printf("si: %d, li: %d, ll: %ld, ul: %lu, s: %d, u: %u\n",
+ si, li, ll, ul, s, u);
+ return 0;
+}
{SCF_CSTR("char"), SCF_LEX_WORD_KEY_CHAR},
+ {SCF_CSTR("short"), SCF_LEX_WORD_KEY_SHORT},
{SCF_CSTR("int"), SCF_LEX_WORD_KEY_INT},
+ {SCF_CSTR("long"), SCF_LEX_WORD_KEY_LONG},
+
+ {SCF_CSTR("signed"), SCF_LEX_WORD_KEY_SIGNED},
+ {SCF_CSTR("unsigned"), SCF_LEX_WORD_KEY_UNSIGNED},
+
{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("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(".quad"), SCF_LEX_WORD_ASM_QUAD},
{SCF_CSTR(".ascii"), SCF_LEX_WORD_ASM_ASCII},
{SCF_CSTR(".asciz"), SCF_LEX_WORD_ASM_ASCIZ},
+
+ {SCF_CSTR("__builtin_va_start"), SCF_LEX_WORD_KEY_VA_START},
+ {SCF_CSTR("__builtin_va_arg"), SCF_LEX_WORD_KEY_VA_ARG},
+ {SCF_CSTR("__builtin_va_end"), SCF_LEX_WORD_KEY_VA_END},
};
static scf_escape_char_t escape_chars[] =
return c;
}
-int scf_lex_open(scf_lex_t** plex, const char* path, scf_string_t* text, int c_version)
+int scf_lex_open(scf_lex_t** plex, const char* path, scf_string_t* text, int c_version, scf_lex_word_t* include)
{
if (!plex || !path)
return -EINVAL;
return -ENOMEM;
}
+ if (include) {
+ lex->included = scf_lex_word_clone(include);
+
+ if (!lex->included) {
+ scf_string_free(lex->file);
+ free(lex);
+ return -ENOMEM;
+ }
+ }
+
if (!text) {
lex->fp = fopen(path, "r");
if (!lex->fp) {
getcwd(cwd, 4095);
scf_loge("open file '%s' failed, errno: %d, default path dir: %s\n", path, errno, cwd);
+ if (lex->included)
+ scf_lex_word_free(lex->included);
+
scf_string_free(lex->file);
free(lex);
return -1;
scf_string_free(lex->file);
+ if (lex->included)
+ scf_lex_word_free(lex->included);
+
if (lex->fp)
fclose(lex->fp);
free(lex);
w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_STRING);
} else {
- if (SCF_C99 == lex->c_version
- && (SCF_CSTR_CMP(s, "restrict")
- || SCF_CSTR_CMP(s, "__restrict")
- || SCF_CSTR_CMP(s, "__restrict__"))) {
-
- scf_string_free(s);
- s = NULL;
-
- return __lex_pop_word(lex, pword);
- }
-
int type = _find_key_word(s);
if (-1 == type)
}
}
+int __lex_drop_space(scf_lex_t* lex, scf_lex_word_t** pword)
+{
+ scf_lex_word_t* w = NULL;
+
+ while (1) {
+ int ret = __lex_pop_word(lex, &w);
+ if (ret < 0)
+ return ret;
+
+ if (SCF_LEX_WORD_SPACE != w->type)
+ break;
+
+ scf_lex_word_free(w);
+ w = NULL;
+ }
+
+ *pword = w;
+ return 0;
+}
+
int __lex_pop_word(scf_lex_t* lex, scf_lex_word_t** pword)
{
scf_list_t* l = NULL;
|| '\r' == c->c || '\t' == c->c
|| ' ' == c->c || '\\' == c->c) {
+ int type = -1;
+
if ('\n' == c->c) {
if (SCF_UTF8_LF == c->flag || lex->asm_flag)
- {
- w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_LF);
- w->text = scf_string_cstr("LF");
- *pword = w;
-
- free(c);
- c = NULL;
-
- lex->nb_lines++;
- lex->pos = 0;
- return 0;
- }
+ type = SCF_LEX_WORD_LF;
lex->nb_lines++;
lex->pos = 0;
- } else
+ } else {
lex->pos++;
+ if ('\t' == c->c || ' ' == c->c || '\\' == c->c)
+ type = SCF_LEX_WORD_SPACE;
+ }
+
+ if (type > 0) {
+ w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type);
+
+ if (SCF_LEX_WORD_LF == type)
+ w->text = scf_string_cstr("LF");
+ else
+ w->text = scf_string_cstr_len(c->utf8, c->len);
+ *pword = w;
+
+ free(c);
+ return 0;
+ }
+
free(c);
c = _lex_pop_char(lex);
}
scf_lex_word_t* w = NULL;
scf_lex_word_t* w1 = NULL;
- int ret = __lex_pop_word(lex, &w);
+ int ret = __lex_drop_space(lex, &w);
if (ret < 0)
return ret;
// parse macro
while (SCF_LEX_WORD_HASH == w->type) {
- ret = __lex_pop_word(lex, &w1);
+ ret = __lex_drop_space(lex, &w1);
if (ret < 0) {
scf_lex_word_free(w);
return ret;
}
- switch (w1->type) {
+ switch (w1->type)
+ {
case SCF_LEX_WORD_KEY_INCLUDE:
+ ret = __parse_macro_include(lex);
+ if (ret < 0)
+ break;
+
case SCF_LEX_WORD_KEY_ENDIF:
scf_lex_push_word(lex, w1);
- *pword = w;
- return 0;
+ w1 = NULL;
+ goto end;
break;
case SCF_LEX_WORD_KEY_IF:
default:
if (lex->asm_flag) {
scf_lex_push_word(lex, w1);
- *pword = w;
- return 0;
+ w1 = NULL;
+ goto end;
}
scf_loge("unknown macro '%s', file: %s, line: %d\n", w1->text->data, w1->file->data, w1->line);
if (ret < 0)
return ret;
- ret = __lex_pop_word(lex, &w);
+ ret = __lex_drop_space(lex, &w);
if (ret < 0)
return ret;
}
if (ret < 0)
return ret;
+end:
+ if (SCF_C99 == lex->c_version
+ && SCF_LEX_WORD_ID == w->type
+ && (SCF_CSTR_CMP(w->text, "restrict")
+ || SCF_CSTR_CMP(w->text, "__restrict")
+ || SCF_CSTR_CMP(w->text, "__restrict__"))) {
+
+ scf_lex_word_free(w);
+ w = NULL;
+
+ return scf_lex_pop_word(lex, pword);
+ }
+
*pword = w;
return 0;
}
typedef struct scf_char_s scf_char_t;
typedef struct scf_lex_s scf_lex_t;
-#define SCF_C89 0
-#define SCF_C99 1
+#define SCF_C89 1
+#define SCF_C99 2
typedef struct {
char* text;
int nb_lines;
int pos;
+ scf_lex_word_t* included; // where cur file is included by '#include'
+
uint8_t asm_flag:1;
};
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 c_version);
+int scf_lex_open (scf_lex_t** plex, const char* path, scf_string_t* text, int c_version, scf_lex_word_t* include);
int scf_lex_close(scf_lex_t* lex);
void scf_lex_push_word(scf_lex_t* lex, scf_lex_word_t* word);
int scf_lex_pop_word (scf_lex_t* lex, scf_lex_word_t** pword);
+int __lex_drop_space(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 __lex_add_macro(scf_lex_t* lex, const char* name, const int64_t value);
int __macro_if_expr(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);
-int __parse_macro_if (scf_lex_t* lex);
-int __parse_macro_else (scf_lex_t* lex);
+int __parse_macro_include(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 __parse_macro_if (scf_lex_t* lex);
+int __parse_macro_else (scf_lex_t* lex);
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);
{
scf_lex_t* lex = NULL;
- if (scf_lex_open(&lex, argv[1], NULL, SCF_C99) < 0) {
+ if (scf_lex_open(&lex, argv[1], NULL, SCF_C99, NULL) < 0) {
scf_loge("\n");
return -1;
}
while (1) {
if (!w1) {
- int ret = __lex_pop_word(lex, &w1);
+ int ret = __lex_drop_space(lex, &w1);
if (ret < 0)
return ret;
}
continue;
}
- int ret = __lex_pop_word(lex, &w2);
+ int ret = __lex_drop_space(lex, &w2);
if (ret < 0) {
scf_lex_word_free(w1);
return ret;
continue;
}
- int ret = __lex_pop_word(lex, &w2);
+ int ret = __lex_drop_space(lex, &w2);
if (ret < 0) {
scf_lex_word_free(w1);
return ret;
int id = 0;
while (1) {
- int ret = __lex_pop_word(lex, &w);
+ int ret = __lex_drop_space(lex, &w);
if (ret < 0)
return ret;
scf_macro_t* m;
scf_macro_t* m0;
- int ret = __lex_pop_word(lex, &w);
+ int ret = __lex_drop_space(lex, &w);
if (ret < 0)
return ret;
scf_macro_free(m);
return ret;
}
+
+ } else if (SCF_LEX_WORD_SPACE == w->type) {
+ scf_lex_word_free(w);
+ w = NULL;
}
pp = &m->text_list;
break;
}
+ w->next = NULL;
+
*pp = w;
pp = &w->next;
w = NULL;
}
- ret = __lex_pop_word(lex, &w);
+ ret = __lex_drop_space(lex, &w);
if (ret < 0) {
scf_macro_free(m);
return ret;
return ret;
}
+
int type = w2->type;
scf_lex_word_free(w2);
return __do_macro_if(lex, 1);
}
+int __parse_macro_include(scf_lex_t* lex)
+{
+ scf_lex_word_t* w = NULL;
+ scf_lex_word_t* w1 = NULL;
+
+ int ret = __lex_drop_space(lex, &w);
+ if (ret < 0)
+ return ret;
+
+ if (SCF_LEX_WORD_CONST_STRING == w->type) {
+ scf_lex_push_word(lex, w);
+ return 0;
+
+ } else if (SCF_LEX_WORD_LT != w->type) {
+ scf_loge("%s:%d:%d, unknown '%s' after '#include'\n", w->file->data, w->line, w->pos, w->text->data);
+
+ scf_lex_word_free(w);
+ return -EINVAL;
+ }
+
+ assert(!w->data.s);
+
+ int type;
+ do {
+ ret = __lex_drop_space(lex, &w1);
+ if (ret < 0) {
+ scf_lex_word_free(w);
+ return ret;
+ }
+
+ type = w1->type;
+
+ if (SCF_LEX_WORD_LF == type || SCF_LEX_WORD_EOF == type) {
+ scf_loge("%s:%d:%d, NOT found '>' after '#include' until '%s'\n", w->file->data, w->line, w->pos, w->text->data);
+
+ scf_lex_word_free(w1);
+ scf_lex_word_free(w);
+ return -EINVAL;
+ }
+
+ if (SCF_LEX_WORD_GT != type) {
+ ret = 0;
+
+ if (w->data.s)
+ ret = scf_string_cat(w->data.s, w1->text);
+ else {
+ w->data.s = scf_string_clone(w1->text);
+ if (!w->data.s)
+ ret = -ENOMEM;
+ }
+
+ if (ret < 0) {
+ scf_lex_word_free(w1);
+ scf_lex_word_free(w);
+ return ret;
+ }
+ }
+
+ ret = scf_string_cat(w->text, w1->text);
+
+ scf_lex_word_free(w1);
+ w1 = NULL;
+
+ if (ret < 0) {
+ scf_lex_word_free(w);
+ return ret;
+ }
+ } while (SCF_LEX_WORD_GT != type);
+
+ w->type = SCF_LEX_WORD_CONST_STRING;
+
+ scf_lex_push_word(lex, w);
+ return 0;
+}
+
int __parse_macro_ifdef(scf_lex_t* lex, int def_flag)
{
scf_lex_word_t* w = NULL;
scf_macro_t* m;
- int ret = __lex_pop_word(lex, &w);
+ int ret = __lex_drop_space(lex, &w);
if (ret < 0)
return ret;
scf_lex_word_t* w0 = NULL;
- int ret = __lex_pop_word(lex, &w0);
+ int ret = __lex_drop_space(lex, &w0);
if (ret < 0)
return ret;
return ret;
default:
- scf_logw("w0: %s, w0->data.u64: %ld\n", w0->text->data, w0->data.u64);
+ scf_logd("w0: %s, w0->data.u64: %ld\n", w0->text->data, w0->data.u64);
*operand = w0;
if (ret < 0)
return ret;
- ret = __lex_pop_word(lex, &op2);
+ ret = __lex_drop_space(lex, &op2);
if (ret < 0)
return ret;
if (ret < 0) \
return ret; \
\
- if (!scf_lex_is_const(w0)) \
+ if (!scf_lex_is_const_integer(w0) && !scf_lex_is_identity(w0)) \
return -EINVAL; \
\
- if (!scf_lex_is_const(w1)) \
+ if (!scf_lex_is_const_integer(w1) && !scf_lex_is_identity(w1)) \
return -EINVAL; \
\
w0->data.i64 = w0->data.i64 op w1->data.i64; \
- scf_logi("op: %s, result: %ld, line: %d, pos: %d\n\n", w_op->text->data, w0->data.i64, w_op->line, w_op->pos); \
+ scf_logd("op: %s, result: %ld, line: %d, pos: %d\n\n", w_op->text->data, w0->data.i64, w_op->line, w_op->pos); \
\
*operand = w0; \
return 0; \
scf_lex_word_t* w0 = *operand;
scf_lex_word_t* w1 = NULL;
- if (!scf_lex_is_const(w0)) {
+ if (!scf_lex_is_const_integer(w0) && !scf_lex_is_identity(w0)) {
scf_loge("\n");
return -EINVAL;
}
if (ret < 0)
return ret;
- if (!scf_lex_is_const(w1)) {
+ if (!scf_lex_is_const_integer(w1) && !scf_lex_is_identity(w1)) {
scf_loge("\n");
return -EINVAL;
}
w0->data.i64 = w0->data.i64 && w1->data.i64;
}
- scf_logi("op: %s, result: %ld, line: %d, pos: %d\n\n", w_op->text->data, w0->data.i64, w_op->line, w_op->pos);
+ scf_logd("op: %s, result: %ld, line: %d, pos: %d\n\n", w_op->text->data, w0->data.i64, w_op->line, w_op->pos);
*operand = w0;
return 0;
scf_lex_word_t* w0 = *operand;
scf_lex_word_t* w1 = NULL;
- if (!scf_lex_is_const(w0)) {
+ if (!scf_lex_is_const_integer(w0) && !scf_lex_is_identity(w0)) {
scf_loge("\n");
return -EINVAL;
}
if (ret < 0)
return ret;
- if (!scf_lex_is_const(w1)) {
+ if (!scf_lex_is_const_integer(w1) && !scf_lex_is_identity(w1)) {
scf_loge("\n");
return -EINVAL;
}
w0->data.i64 = w0->data.i64 || w1->data.i64;
}
- scf_logi("op: %s, result: %ld, line: %d, pos: %d\n\n", w_op->text->data, w0->data.i64, w_op->line, w_op->pos);
+ scf_logd("op: %s, result: %ld, line: %d, pos: %d\n\n", w_op->text->data, w0->data.i64, w_op->line, w_op->pos);
*operand = w0;
return 0;
int n_rps = 0;
while (1) {
- ret = __lex_pop_word(lex, &w0);
+ ret = __lex_drop_space(lex, &w0);
if (ret < 0)
return ret;
w0->type = SCF_LEX_WORD_CONST_I64;
*operand = w0;
- scf_logi("w0: %s, result: %ld\n", w0->text->data, w0->data.i64);
+ scf_logd("w0: %s, result: %ld\n", w0->text->data, w0->data.i64);
w0 = NULL;
while (n_rps < n_lps) {
- ret = __lex_pop_word(lex, &w0);
+ ret = __lex_drop_space(lex, &w0);
if (ret < 0)
return ret;
\
scf_lex_word_t* w0 = *operand; \
\
- if (!scf_lex_is_const(w0)) \
+ if (!scf_lex_is_const_integer(w0) && !scf_lex_is_identity(w0)) \
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); \
+ scf_logd("op: %s, result: %ld, line: %d, pos: %d\n", w_op->text->data, w0->data.i64, w_op->line, w_op->pos); \
return 0; \
}
if (ret < 0)
return ret;
- ret = __lex_pop_word(lex, &op2);
+ ret = __lex_drop_space(lex, &op2);
if (ret < 0)
return ret;
if (ret < 0)
return ret;
- ret = __lex_pop_word(lex, &op2);
+ ret = __lex_drop_space(lex, &op2);
if (ret < 0)
return ret;
}
scf_lex_word_t* w0 = *operand;
scf_lex_word_t* op2 = NULL;
- if (!scf_lex_is_const(w0))
+ if (!scf_lex_is_const_integer(w0) && !scf_lex_is_identity(w0))
return -EINVAL;
- ret = __lex_pop_word(lex, &op2);
+ ret = __lex_drop_space(lex, &op2);
if (ret < 0)
return ret;
int ret = 0;
while (1) {
- ret = __lex_pop_word(lex, &w);
+ ret = __lex_drop_space(lex, &w);
if (ret < 0)
goto error;
goto error;
}
- if (!scf_lex_is_const(w)) {
+ if (!scf_lex_is_const_integer(w) && !scf_lex_is_identity(w)) {
+
scf_loge("operand '%s' is NOT CONST in macro expr, file: %s, line: %d\n",
w->text->data, w->file->data, w->line);
goto error;
}
- scf_logi("w: %s, w->data.u64: %ld\n", w->text->data, w->data.u64);
+ scf_logd("w: %s, w->data.u64: %ld\n", w->text->data, w->data.u64);
operand = w;
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_logd("\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);
+ scf_logd("final flag: %d\n", ret);
return ret;
}
#include"scf_x64.h"
#include"scf_elf_link.h"
+static char* __h_files[] =
+{
+ "../sysroot/lib/__builtin__.h",
+};
+
static char* __objs[] =
{
"_start.o",
void usage(char* path)
{
- fprintf(stderr, "Usage: %s [-std=..] [-c] [-d] [-t] [-a arch] [-s sysroot] [-Iinclude / -I include] [-lsofile / -l sofile] [-Lsopath / -L sopath] [-o out] src0 [src1]\n\n", path);
+ fprintf(stderr, "Usage: %s [-std=..] [-c] [-p/-t] [-d] [-a arch] [-s sysroot] [-Dmacro / -D macro] [-Iinclude / -I include] [-lsofile / -l sofile] [-Lsopath / -L sopath] [-o out] src0 [src1]\n\n", path);
fprintf(stderr, "-std: c89 or c99 version\n");
fprintf(stderr, "-c: only compile, not link\n");
- fprintf(stderr, "-t: only 3ac code, not compile\n");
+ fprintf(stderr, "-p: only parse, not compile\n");
+ fprintf(stderr, "-t: only 3ac code, not compile\n\n");
+
fprintf(stderr, "-a: select cpu arch (x64, arm64, naja, or eda), default is x64\n");
fprintf(stderr, "-s: sysroot dir, default is '../lib'\n");
- fprintf(stderr, "-d: output dynamic library .so\n");
+ fprintf(stderr, "-d: output dynamic library .so\n\n");
+
+ fprintf(stderr, "-D: define a macro\n");
fprintf(stderr, "-I: include paths for .h file\n");
fprintf(stderr, "-l: file name of lib*.so / lib*.a, NOT include prefix 'lib' & post fix '.so' or '.a'\n");
fprintf(stderr, "-L: file paths for .so / .a file\n");
return 0;
}
+int add_macro(scf_vector_t* macros, const char* s)
+{
+ scf_string_t* file;
+ scf_lex_word_t* w0;
+ scf_lex_word_t* w1;
+ scf_macro_t* m;
+
+ double d = 0.0;
+ int64_t i64 = 1;
+ int type = SCF_LEX_WORD_CONST_I64;
+
+ scf_logi("s: %s\n", s);
+
+ file = scf_string_cstr("__stdc__.h");
+ if (!file)
+ return -ENOMEM;
+
+ w0 = scf_lex_word_alloc(file, 0, 0, SCF_LEX_WORD_ID);
+ if (!w0)
+ goto w0_error;
+
+ const char* p = s;
+ while (*p && '=' != *p)
+ p++;
+
+ w0->text = scf_string_cstr_len(s, (size_t)(p - s));
+ if (!w0->text)
+ goto t0_error;
+
+ if ('=' == *p) {
+ p++;
+
+ s = p;
+ while (*p && '.' != *p)
+ p++;
+
+ scf_logi("s: %s\n", s);
+
+ if ('.' == *p) {
+ type = SCF_LEX_WORD_CONST_DOUBLE;
+ d = atof(s);
+
+ } else if ('0' <= *s && *s <= '9')
+ i64 = atol(s);
+ else
+ type = SCF_LEX_WORD_CONST_STRING;
+ }
+
+ w1 = scf_lex_word_alloc(file, 0, 0, type);
+ if (!w1)
+ goto t0_error;
+
+ if (SCF_LEX_WORD_CONST_I64 == type) {
+ w1->data.i64 = i64;
+
+ char buf[128];
+ int n = snprintf(buf, sizeof(buf) - 1, "%ld", i64);
+
+ w1->text = scf_string_cstr_len(buf, n);
+
+ } else if (SCF_LEX_WORD_CONST_DOUBLE == type) {
+ w1->data.d = d;
+
+ w1->text = scf_string_cstr(s);
+ } else {
+ w1->data.s = scf_string_cstr(s);
+ if (!w1->data.s)
+ goto t1_error;
+
+ w1->text = scf_string_clone(w1->data.s);
+ }
+ if (!w1->text)
+ goto t1_error;
+
+ m = scf_macro_alloc(w0);
+ if (!m)
+ goto t1_error;
+
+ m->text_list = w1;
+ w1->next = NULL;
+ w1 = NULL;
+ w0 = NULL;
+
+ scf_string_free(file);
+ file = NULL;
+
+ int ret = scf_vector_add(macros, m);
+ if (ret < 0) {
+ scf_macro_free(m);
+ return ret;
+ }
+
+ m->def_flag = 1;
+ return 0;
+
+t1_error:
+ scf_lex_word_free(w1);
+t0_error:
+ scf_lex_word_free(w0);
+w0_error:
+ scf_string_free(file);
+ return -ENOMEM;
+}
+
int main(int argc, char* argv[])
{
if (argc < 2) {
scf_vector_t* sofiles = scf_vector_alloc();
scf_vector_t* srcs = scf_vector_alloc();
scf_vector_t* objs = scf_vector_alloc();
+ scf_vector_t* macros = scf_vector_alloc();
if (!inc_paths
|| !lib_paths
|| !lib_files
- || !afiles || !sofiles || !srcs || !objs) {
+ || !afiles || !sofiles || !srcs || !objs
+ || !macros) {
ret = -ENOMEM;
goto error;
}
char* out = NULL;
int link = 1;
int _3ac = 0;
+ int _parse = 0;
int dyn = 0;
int c_version = SCF_C99;
int i;
+ for (i = 0; i < sizeof(__h_files) / sizeof(__h_files[0]); i++) {
+
+ ret = scf_vector_add(srcs, __h_files[i]);
+ if (ret < 0)
+ goto error;
+ }
+
for (i = 1; i < argc; i++) {
if ('-' == argv[i][0]) {
continue;
}
+ if ('p' == argv[i][1]) {
+ link = 0;
+ _3ac = 0;
+ _parse = 1;
+ continue;
+ }
+
if ('t' == argv[i][1]) {
link = 0;
_3ac = 1;
+ _parse = 0;
continue;
}
dyn = 1;
link = 1;
_3ac = 0;
+ _parse = 0;
continue;
}
scf_vector_t* vec = NULL;
switch (argv[i][1]) {
+ case 'D':
+ vec = macros;
+ break;
+
case 'I':
vec = inc_paths;
break;
} else
fname = argv[i] + 2;
- ret = scf_vector_add(vec, fname);
+ if (vec == macros)
+ ret = add_macro(macros, fname);
+ else
+ ret = scf_vector_add(vec, fname);
if (ret < 0)
goto error;
printf("\n");
+ switch (c_version) {
+ case SCF_C99:
+ ret = add_macro(macros, "__STDC_VERSION__=199901");
+ if (ret < 0)
+ goto error;
+
+ case SCF_C89:
+ ret = add_macro(macros, "__STDC__=1");
+ if (ret < 0)
+ goto error;
+ break;
+ };
+
char* obj = "1.o";
char* exec = "1.out";
assert(file);
- ret = scf_parse_file(parse, file);
+ scf_vector_t* _macros = scf_vector_clone(macros);
+ if (!_macros) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ scf_macro_t* m;
+ int j;
+
+ for (j = 0; j < _macros->size; j++) {
+ m = _macros->data[j];
+
+ m->refs++;
+ }
+
+ ret = scf_parse_file(parse, file, &_macros, NULL);
+
+ if (_macros) {
+ scf_vector_clear(_macros, ( void (*)(void*) )scf_macro_free);
+ scf_vector_free(_macros);
+ _macros = NULL;
+ }
+
if (ret < 0) {
scf_loge("parse file '%s' failed\n", file);
goto error;
}
}
- ret = scf_parse_compile(parse, arch, _3ac);
- if (ret < 0) {
- scf_loge("\n");
- goto error;
- }
+ if (!_parse) {
+ ret = scf_parse_compile(parse, arch, _3ac);
+ if (ret < 0) {
+ scf_loge("\n");
+ goto error;
+ }
- ret = scf_parse_to_obj(parse, obj, arch);
- if (ret < 0) {
- scf_loge("\n");
- goto error;
+ ret = scf_parse_to_obj(parse, obj, arch);
+ if (ret < 0) {
+ scf_loge("\n");
+ goto error;
+ }
}
scf_parse_close(parse);
scf_vector_free(objs);
}
+ if (macros) {
+ scf_vector_clear(macros, ( void (*)(void*) )scf_macro_free);
+ scf_vector_free(macros);
+ }
+
return ret;
}
return SCF_DFA_ERROR;
}
- scf_logi("d->expr: %p, OP: %d\n", d->expr, d->expr->type);
+ scf_logd("d->expr: %p, OP: %d\n", d->expr, d->expr->type);
cd->func = node_pf;
cd->call = node_call;
scf_stack_pop(s);
- scf_logi("d->expr: %p\n", d->expr);
+ scf_logd("d->expr: %p\n", d->expr);
if (cd->parent_expr) {
if (cd->func)
scf_loge("\n");
return SCF_DFA_ERROR;
}
- scf_logi("d->expr: %p\n", d->expr);
+ scf_logd("d->expr: %p\n", d->expr);
if (!cd->argv)
cd->argv = scf_vector_alloc();
} dfa_fun_data_t;
+int _type_find_type(scf_dfa_t* dfa, dfa_identity_t* id);
+
int _function_add_function(scf_dfa_t* dfa, dfa_data_t* d)
{
scf_parse_t* parse = dfa->priv;
assert(t);
if (!t->type) {
- scf_loge("NO type found for '%s', file: %s, line: %d\n",
- t->identity->text->data,
- t->identity->file->data, t->identity->line);
+ int ret = _type_find_type(dfa, t);
- free(t);
- return SCF_DFA_ERROR;
+ if (ret < 0 || !t->type) {
+ scf_loge("NO type found for '%s', file: %s, line: %d\n",
+ t->identity->text->data,
+ t->identity->file->data, t->identity->line);
+
+ free(t);
+ return SCF_DFA_ERROR;
+ }
}
break;
assert(v && v->identity);
if (!t->type) {
- scf_loge("NO type found for '%s', file: %s, line: %d\n",
- t->identity->text->data,
- t->identity->file->data, t->identity->line);
+ int ret = _type_find_type(dfa, t);
- free(t);
- free(v);
- return SCF_DFA_ERROR;
+ if (ret < 0 || !t->type) {
+ scf_loge("NO type found for '%s', file: %s, line: %d\n",
+ t->identity->text->data,
+ t->identity->file->data, t->identity->line);
+
+ free(t);
+ free(v);
+ return SCF_DFA_ERROR;
+ }
}
break;
default:
w = v->identity;
if (SCF_VAR_VOID == t->type->node.type && 0 == t->nb_pointers) {
- scf_loge("\n");
- return SCF_DFA_ERROR;
+ if (v) {
+ free(v);
+ v = NULL;
+ }
+
+ free(t);
+ t = NULL;
+ return SCF_DFA_NEXT_WORD;
}
if (!d->current_var) {
static int _include_action_path(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];
- scf_lex_t* lex = parse->lex;
- scf_block_t* cur = parse->ast->current_block;
+ assert(words->size >= 2);
+
+ scf_parse_t* parse = dfa->priv;
+ dfa_data_t* d = data;
+ scf_lex_word_t* include = words->data[words->size - 2];
+ scf_lex_word_t* w = words->data[words->size - 1];
+ scf_lex_t* lex = parse->lex;
+ scf_block_t* cur = parse->ast->current_block;
assert(w->data.s);
if (ret < 0)
return ret;
else if (0 == ret) {
- scf_loge("include '%s' NOT found, at file: %s, line:%d\n", w->data.s->data, w->file->data, w->line);
+ scf_loge("%s:%d:%d, include file '%s' NOT found\n", w->file->data, w->line, w->pos, w->data.s->data);
return SCF_DFA_ERROR;
}
parse->lex = NULL;
- ret = scf_parse_file(parse, path);
+ ret = scf_parse_file(parse, path, &lex->macros, include);
if (ret < 0) {
scf_loge("parse file '%s' failed, 'include' line: %d\n", path, w->line);
goto error;
}
- if (parse->lex && parse->lex != lex && parse->lex->macros) { // copy macros
+ if (parse->lex && parse->lex != lex && parse->lex->macros) {
+ assert(!lex->macros);
- if (!lex->macros) {
- lex->macros = scf_vector_clone(parse->lex->macros);
-
- if (!lex->macros) {
- ret = -ENOMEM;
- goto error;
- }
- } else {
- ret = scf_vector_cat(lex->macros, parse->lex->macros);
- if (ret < 0)
- goto error;
- }
-
- scf_macro_t* m;
- int i;
- for (i = 0; i < parse->lex->macros->size; i++) {
- m = parse->lex->macros->data[i];
- m->refs++;
- }
+ lex->macros = parse->lex->macros;
+ parse->lex->macros = NULL;
}
ret = SCF_DFA_NEXT_WORD;
md->new = NULL;
- scf_logi("d->expr: %p\n", d->expr);
+ scf_logd("d->expr: %p\n", d->expr);
return SCF_DFA_NEXT_WORD;
}
d->nb_lps = 0;
d->nb_rps = 0;
- scf_logi("\n");
return SCF_DFA_OK;
}
int __class_add_type(scf_ast_t* ast, scf_lex_word_t* key, scf_lex_word_t* name);
+typedef struct {
+ int type;
+ int n;
+ int keys[8];
+
+} type_filter_t;
+
+static type_filter_t base_type_filters[] =
+{
+ {SCF_VAR_U8, 2, SCF_LEX_WORD_KEY_UNSIGNED, SCF_LEX_WORD_KEY_CHAR},
+ {SCF_VAR_U16, 2, SCF_LEX_WORD_KEY_UNSIGNED, SCF_LEX_WORD_KEY_SHORT},
+ {SCF_VAR_U16, 3, SCF_LEX_WORD_KEY_UNSIGNED, SCF_LEX_WORD_KEY_SHORT, SCF_LEX_WORD_KEY_INT},
+ {SCF_VAR_U32, 2, SCF_LEX_WORD_KEY_UNSIGNED, SCF_LEX_WORD_KEY_INT},
+ {SCF_VAR_U64, 2, SCF_LEX_WORD_KEY_UNSIGNED, SCF_LEX_WORD_KEY_LONG},
+ {SCF_VAR_U64, 3, SCF_LEX_WORD_KEY_UNSIGNED, SCF_LEX_WORD_KEY_LONG, SCF_LEX_WORD_KEY_LONG},
+
+ {SCF_VAR_I8, 2, SCF_LEX_WORD_KEY_SIGNED, SCF_LEX_WORD_KEY_CHAR},
+ {SCF_VAR_I16, 2, SCF_LEX_WORD_KEY_SIGNED, SCF_LEX_WORD_KEY_SHORT},
+ {SCF_VAR_I16, 3, SCF_LEX_WORD_KEY_SIGNED, SCF_LEX_WORD_KEY_SHORT, SCF_LEX_WORD_KEY_INT},
+ {SCF_VAR_I32, 2, SCF_LEX_WORD_KEY_SIGNED, SCF_LEX_WORD_KEY_INT},
+ {SCF_VAR_I64, 2, SCF_LEX_WORD_KEY_SIGNED, SCF_LEX_WORD_KEY_LONG},
+ {SCF_VAR_I64, 3, SCF_LEX_WORD_KEY_SIGNED, SCF_LEX_WORD_KEY_LONG, SCF_LEX_WORD_KEY_LONG},
+
+ {SCF_VAR_INTPTR, 2, SCF_LEX_WORD_KEY_LONG, SCF_LEX_WORD_KEY_INT},
+ {SCF_VAR_INTPTR, 2, SCF_LEX_WORD_KEY_LONG, SCF_LEX_WORD_KEY_LONG},
+ {SCF_VAR_DOUBLE, 2, SCF_LEX_WORD_KEY_LONG, SCF_LEX_WORD_KEY_DOUBLE},
+
+ {SCF_VAR_I16, 2, SCF_LEX_WORD_KEY_SHORT, SCF_LEX_WORD_KEY_INT},
+};
+
+static int _base_type_filter(scf_dfa_t* dfa, scf_vector_t* words, scf_stack_t* s)
+{
+ if (s->size <= 1)
+ return 0;
+
+ scf_parse_t* parse = dfa->priv;
+ scf_ast_t* ast = parse->ast;
+ scf_lex_word_t* w;
+ dfa_identity_t* id;
+ type_filter_t* tf;
+ int i;
+ int j;
+
+ assert(words->size >= s->size);
+
+ i = words->size - 2;
+ j = s->size - 1;
+
+ while (i >= 0 && j > 0) {
+ w = words->data[i];
+
+ if (!scf_lex_is_base_type(w))
+ break;
+
+ i--;
+ j--;
+ }
+
+ assert(j >= 0);
+
+ if (s->size - j <= 1)
+ return 0;
+
+ for (i = 0; i < sizeof(base_type_filters) / sizeof(base_type_filters[0]); i++) {
+ tf = &base_type_filters[i];
+
+ if (tf->n != s->size - j)
+ continue;
+
+ int k;
+ for (k = j; k < s->size; k++) {
+ id = s->data[k];
+
+ if (id->type_w->type != tf->keys[k - j])
+ break;
+ }
+
+ if (k >= s->size) {
+ id = s->data[j];
+
+ id->type = scf_block_find_type_type(ast->current_block, tf->type);
+ if (!id->type)
+ goto error;
+
+ w = dfa->ops->pop_word(dfa);
+ if (!w)
+ return -ENOMEM;
+ dfa->ops->push_word(dfa, w);
+
+ if (!scf_lex_is_base_type(w)) {
+
+ while (s->size > j + 1) {
+ id = scf_stack_pop(s);
+
+ free(id);
+ id = NULL;
+ }
+ }
+
+ return 0;
+ }
+ }
+
+error:
+ id = s->data[j];
+
+ scf_loge("%s:%d:%d, NOT support type: ", id->type_w->file->data, id->type_w->line, id->type_w->pos);
+
+ for ( ; j < s->size; j++) {
+ id = s->data[j];
+
+ printf("%s ", id->type_w->text->data);
+ }
+ printf("\n");
+
+ return -1;
+}
+
static int _type_is__struct(scf_dfa_t* dfa, void* word)
{
scf_lex_word_t* w = word;
d->inline_flag = 0;
d->typedef_flag = 0;
+ if (_base_type_filter(dfa, words, s) < 0)
+ return SCF_DFA_ERROR;
+
return SCF_DFA_NEXT_WORD;
}
}
}
- ret = _type_find_type(dfa, type);
- if (ret < 0) {
- scf_loge("\n");
- return ret;
+ if (!type->type) {
+ ret = _type_find_type(dfa, type);
+ if (ret < 0) {
+ scf_loge("\n");
+ return ret;
+ }
}
if (d->typedef_flag) {
static int _type_action_star(scf_dfa_t* dfa, scf_vector_t* words, void* data)
{
- dfa_data_t* d = data;
- dfa_identity_t* id = scf_stack_top(d->current_identities);
+ dfa_data_t* d = data;
+ dfa_identity_t* id = scf_stack_top(d->current_identities);
assert(id);
SCF_DFA_MODULE_NODE(dfa, type, _struct, _type_is__struct, NULL);
SCF_DFA_MODULE_NODE(dfa, type, _typedef, scf_dfa_is_typedef, _type_action_typedef);
- SCF_DFA_MODULE_NODE(dfa, type, _const, scf_dfa_is_const, _type_action_const);
SCF_DFA_MODULE_NODE(dfa, type, _static, scf_dfa_is_static, _type_action_static);
SCF_DFA_MODULE_NODE(dfa, type, _extern, scf_dfa_is_extern, _type_action_extern);
SCF_DFA_MODULE_NODE(dfa, type, _inline, scf_dfa_is_inline, _type_action_inline);
+ SCF_DFA_MODULE_NODE(dfa, type, _const, scf_dfa_is_const, _type_action_const);
+ SCF_DFA_MODULE_NODE(dfa, type, vconst, scf_dfa_is_const, _type_action_const);
+
SCF_DFA_MODULE_NODE(dfa, type, base_type, scf_dfa_is_base_type, _type_action_base_type);
SCF_DFA_MODULE_NODE(dfa, type, identity, scf_dfa_is_identity, _type_action_identity);
SCF_DFA_MODULE_NODE(dfa, type, star, scf_dfa_is_star, _type_action_star);
SCF_DFA_GET_MODULE_NODE(dfa, type, entry, entry);
SCF_DFA_GET_MODULE_NODE(dfa, type, _typedef, _typedef);
- SCF_DFA_GET_MODULE_NODE(dfa, type, _const, _const);
SCF_DFA_GET_MODULE_NODE(dfa, type, _static, _static);
SCF_DFA_GET_MODULE_NODE(dfa, type, _extern, _extern);
SCF_DFA_GET_MODULE_NODE(dfa, type, _inline, _inline);
+ SCF_DFA_GET_MODULE_NODE(dfa, type, _const, _const);
+ SCF_DFA_GET_MODULE_NODE(dfa, type, vconst, vconst);
SCF_DFA_GET_MODULE_NODE(dfa, type, _struct, _struct);
SCF_DFA_GET_MODULE_NODE(dfa, type, base_type, base_type);
scf_dfa_node_add_child(_extern, _const);
scf_dfa_node_add_child(_inline, _const);
+ // for long long, long int, long double, short int, ...
+ scf_dfa_node_add_child(base_type, base_type);
+
// struct / union / class
scf_dfa_node_add_child(_struct, type_name);
scf_dfa_node_add_child(type_name, class_semicolon); // only declare
scf_dfa_node_add_child(base_type, var_name);
scf_dfa_node_add_child(type_name, var_name);
+ // const pointer, like 'uint8_t* const p'
+ scf_dfa_node_add_child(star, vconst);
+ scf_dfa_node_add_child(vconst, var_name);
+
// multi-return-value function
scf_dfa_node_add_child(base_type, comma);
scf_dfa_node_add_child(star, comma);
d->nb_lss = 0;
d->nb_rss = 0;
- id = scf_stack_pop(d->current_identities);
- assert(id && id->type);
- free(id);
- id = NULL;
+ while (d->current_identities->size > 0)
+ {
+ id = scf_stack_pop(d->current_identities);
+ assert(id && id->type);
+
+ free(id);
+ id = NULL;
+ }
if (d->current_var) {
scf_variable_size(d->current_var);
{"intptr_t", SCF_VAR_INTPTR, sizeof(void*)},
{"uintptr_t", SCF_VAR_UINTPTR, sizeof(void*)},
{"funcptr", SCF_FUNCTION_PTR, sizeof(void*)},
+
+ {"short", SCF_VAR_I16, 2},
+ {"signed", SCF_VAR_INT, 4},
+ {"unsigned", SCF_VAR_U32, 4},
+ {"long", SCF_VAR_INTPTR, sizeof(void*)},
};
int scf_parse_open(scf_parse_t** pparse, const scf_vector_t* inc_paths, int c_version)
return 0;
}
-int scf_parse_file(scf_parse_t* parse, const char* path)
+int scf_parse_file(scf_parse_t* parse, const char* path, scf_vector_t** macros, scf_lex_word_t* include)
{
if (!parse || !path)
return -EINVAL;
lex = cur->lex_list;
while (lex) {
- if (!strcmp(lex->file->data, path))
- return 0;
+ if (!strcmp(lex->file->data, path)) {
+
+ if (!include) {
+ scf_loge("repeated compile file '%s'\n", path);
+ return SCF_DFA_ERROR;
+ }
+
+ assert(lex->included);
+
+ scf_logw("%s:%d:%d, repeated #include file '%s', prev at %s:%d:%d\n",
+ include->file->data, include->line, include->pos, path,
+ lex->included->file->data, lex->included->line, lex->included->pos);
+ }
lex = lex->next;
}
- if (scf_lex_open(&parse->lex, path, NULL, parse->c_version) < 0)
+ if (scf_lex_open(&parse->lex, path, NULL, parse->c_version, include) < 0)
return -1;
if (cur == ast->root_block)
parse->lex->next = cur->lex_list;
cur->lex_list = parse->lex;
+ parse->lex->macros = *macros;
+ *macros = NULL;
+
dfa_data_t* d = parse->dfa_data;
scf_lex_word_t* w = NULL;
int scf_parse_open (scf_parse_t** pparse, const scf_vector_t* inc_paths, int c_version);
int scf_parse_close(scf_parse_t* parse);
-int scf_parse_file(scf_parse_t* parse, const char* path);
-
+int scf_parse_file (scf_parse_t* parse, const char* path, scf_vector_t** macros, scf_lex_word_t* include);
int scf_parse_compile(scf_parse_t* parse, const char* arch, int _3ac);
-int scf_parse_to_obj (scf_parse_t* parse, const char* out, const char* arch);
+int scf_parse_to_obj (scf_parse_t* parse, const char* out, const char* arch);
int _find_global_var(scf_node_t* node, void* arg, scf_vector_t* vec);
int _find_function (scf_node_t* node, void* arg, scf_vector_t* vec);
--- /dev/null
+#ifndef _FEATURES_H
+#define _FEATURES_H
+
+#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE)
+#define _GNU_SOURCE 1
+#endif
+
+#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE)
+#define _BSD_SOURCE 1
+#endif
+
+#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \
+ && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \
+ && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__)
+#define _BSD_SOURCE 1
+#define _XOPEN_SOURCE 700
+#endif
+
+#if __STDC_VERSION__ >= 199901L
+#define __restrict restrict
+#elif !defined(__GNUC__)
+#define __restrict
+#endif
+
+#if __STDC_VERSION__ >= 199901L || defined(__cplusplus)
+#define __inline inline
+#elif !defined(__GNUC__)
+#define __inline
+#endif
+
+#if __STDC_VERSION__ >= 201112L
+#elif defined(__GNUC__)
+#define _Noreturn __attribute__((__noreturn__))
+#else
+#define _Noreturn
+#endif
+
+#define __REDIR(x,y) __typeof__(x) x __asm__(#y)
+
+#endif
#elif defined(__cplusplus)
#define NULL 0L
#else
-#define NULL ((void*)0)
+//#define NULL ((void*)0)
#endif
#undef EOF
--- /dev/null
+struct __builtin_va_list
+{
+ uint8_t* iptr;
+ uint8_t* fptr;
+ uint8_t* optr;
+
+ intptr_t ireg;
+ intptr_t freg;
+ intptr_t others;
+};