mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
foreign import x {"foo.lib", "bar.lib"}
This commit is contained in:
@@ -69,6 +69,10 @@ compare_byte_ptrs :: proc "contextless" (a, b: ^byte, n: int) -> int {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compare_ptrs :: inline proc "contextless" (a, b: rawptr, n: int) -> int {
|
||||||
|
return compare_byte_ptrs((^byte)(a), (^byte)(b), n);
|
||||||
|
}
|
||||||
|
|
||||||
ptr_offset :: proc "contextless" (ptr: $P/^$T, n: int) -> P {
|
ptr_offset :: proc "contextless" (ptr: $P/^$T, n: int) -> P {
|
||||||
new := int(uintptr(ptr)) + size_of(T)*n;
|
new := int(uintptr(ptr)) + size_of(T)*n;
|
||||||
return P(uintptr(new));
|
return P(uintptr(new));
|
||||||
|
|||||||
+21
-19
@@ -2615,37 +2615,39 @@ void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) {
|
|||||||
Scope *parent_scope = ctx->scope;
|
Scope *parent_scope = ctx->scope;
|
||||||
GB_ASSERT(parent_scope->flags&ScopeFlag_File);
|
GB_ASSERT(parent_scope->flags&ScopeFlag_File);
|
||||||
|
|
||||||
String fullpath = fl->fullpath;
|
GB_ASSERT(fl->fullpaths.count > 0);
|
||||||
|
String fullpath = fl->fullpaths[0];
|
||||||
String library_name = path_to_entity_name(fl->library_name.string, fullpath);
|
String library_name = path_to_entity_name(fl->library_name.string, fullpath);
|
||||||
if (is_blank_ident(library_name)) {
|
if (is_blank_ident(library_name)) {
|
||||||
error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));
|
error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fl->collection_name != "system") {
|
// if (fl->collection_name != "system") {
|
||||||
char *c_str = gb_alloc_array(heap_allocator(), char, fullpath.len+1);
|
// char *c_str = gb_alloc_array(heap_allocator(), char, fullpath.len+1);
|
||||||
defer (gb_free(heap_allocator(), c_str));
|
// defer (gb_free(heap_allocator(), c_str));
|
||||||
gb_memmove(c_str, fullpath.text, fullpath.len);
|
// gb_memmove(c_str, fullpath.text, fullpath.len);
|
||||||
c_str[fullpath.len] = '\0';
|
// c_str[fullpath.len] = '\0';
|
||||||
|
|
||||||
gbFile f = {};
|
// gbFile f = {};
|
||||||
gbFileError file_err = gb_file_open(&f, c_str);
|
// gbFileError file_err = gb_file_open(&f, c_str);
|
||||||
defer (gb_file_close(&f));
|
// defer (gb_file_close(&f));
|
||||||
|
|
||||||
switch (file_err) {
|
// switch (file_err) {
|
||||||
case gbFileError_Invalid:
|
// case gbFileError_Invalid:
|
||||||
error(decl, "Invalid file or cannot be found ('%.*s')", LIT(fullpath));
|
// error(decl, "Invalid file or cannot be found ('%.*s')", LIT(fullpath));
|
||||||
return;
|
// return;
|
||||||
case gbFileError_NotExists:
|
// case gbFileError_NotExists:
|
||||||
error(decl, "File cannot be found ('%.*s')", LIT(fullpath));
|
// error(decl, "File cannot be found ('%.*s')", LIT(fullpath));
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
GB_ASSERT(fl->library_name.pos.line != 0);
|
GB_ASSERT(fl->library_name.pos.line != 0);
|
||||||
fl->library_name.string = library_name;
|
fl->library_name.string = library_name;
|
||||||
|
|
||||||
Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid,
|
Entity *e = alloc_entity_library_name(parent_scope, fl->library_name, t_invalid,
|
||||||
fl->fullpath, library_name);
|
fl->fullpaths, library_name);
|
||||||
add_entity(ctx->checker, parent_scope, nullptr, e);
|
add_entity(ctx->checker, parent_scope, nullptr, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -124,7 +124,7 @@ struct Entity {
|
|||||||
Scope *scope;
|
Scope *scope;
|
||||||
} ImportName;
|
} ImportName;
|
||||||
struct {
|
struct {
|
||||||
String path;
|
Array<String> paths;
|
||||||
String name;
|
String name;
|
||||||
} LibraryName;
|
} LibraryName;
|
||||||
i32 Nil;
|
i32 Nil;
|
||||||
@@ -278,9 +278,9 @@ Entity *alloc_entity_import_name(Scope *scope, Token token, Type *type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity *alloc_entity_library_name(Scope *scope, Token token, Type *type,
|
Entity *alloc_entity_library_name(Scope *scope, Token token, Type *type,
|
||||||
String path, String name) {
|
Array<String> paths, String name) {
|
||||||
Entity *entity = alloc_entity(Entity_LibraryName, scope, token, type);
|
Entity *entity = alloc_entity(Entity_LibraryName, scope, token, type);
|
||||||
entity->LibraryName.path = path;
|
entity->LibraryName.paths = paths;
|
||||||
entity->LibraryName.name = name;
|
entity->LibraryName.name = name;
|
||||||
entity->state = EntityState_Resolved; // TODO(bill): Is this correct?
|
entity->state = EntityState_Resolved; // TODO(bill): Is this correct?
|
||||||
return entity;
|
return entity;
|
||||||
|
|||||||
+16
-14
@@ -1332,22 +1332,24 @@ void ir_add_foreign_library_path(irModule *m, Entity *e) {
|
|||||||
GB_ASSERT(e->kind == Entity_LibraryName);
|
GB_ASSERT(e->kind == Entity_LibraryName);
|
||||||
GB_ASSERT(e->flags & EntityFlag_Used);
|
GB_ASSERT(e->flags & EntityFlag_Used);
|
||||||
|
|
||||||
String library_path = e->LibraryName.path;
|
for_array(i, e->LibraryName.paths) {
|
||||||
if (library_path.len == 0) {
|
String library_path = e->LibraryName.paths[i];
|
||||||
return;
|
if (library_path.len == 0) {
|
||||||
}
|
continue;
|
||||||
|
|
||||||
for_array(path_index, m->foreign_library_paths) {
|
|
||||||
String path = m->foreign_library_paths[path_index];
|
|
||||||
#if defined(GB_SYSTEM_WINDOWS)
|
|
||||||
if (str_eq_ignore_case(path, library_path)) {
|
|
||||||
#else
|
|
||||||
if (str_eq(path, library_path)) {
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for_array(path_index, m->foreign_library_paths) {
|
||||||
|
String path = m->foreign_library_paths[path_index];
|
||||||
|
#if defined(GB_SYSTEM_WINDOWS)
|
||||||
|
if (str_eq_ignore_case(path, library_path)) {
|
||||||
|
#else
|
||||||
|
if (str_eq(path, library_path)) {
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array_add(&m->foreign_library_paths, library_path);
|
||||||
}
|
}
|
||||||
array_add(&m->foreign_library_paths, library_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -253,7 +253,6 @@ bool parse_build_flags(Array<String> args) {
|
|||||||
add_flag(&build_flags, BuildFlag_CrossLibDir, str_lit("cross-lib-dir"), BuildFlagParam_String);
|
add_flag(&build_flags, BuildFlag_CrossLibDir, str_lit("cross-lib-dir"), BuildFlagParam_String);
|
||||||
add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None);
|
add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None);
|
||||||
|
|
||||||
|
|
||||||
GB_ASSERT(args.count >= 3);
|
GB_ASSERT(args.count >= 3);
|
||||||
Array<String> flag_args = array_slice(args, 3, args.count);
|
Array<String> flag_args = array_slice(args, 3, args.count);
|
||||||
|
|
||||||
@@ -877,9 +876,9 @@ int main(int arg_count, char **arg_ptr) {
|
|||||||
gbString lib_str = gb_string_make(heap_allocator(), "");
|
gbString lib_str = gb_string_make(heap_allocator(), "");
|
||||||
defer (gb_string_free(lib_str));
|
defer (gb_string_free(lib_str));
|
||||||
char lib_str_buf[1024] = {0};
|
char lib_str_buf[1024] = {0};
|
||||||
|
|
||||||
for_array(i, ir_gen.module.foreign_library_paths) {
|
for_array(i, ir_gen.module.foreign_library_paths) {
|
||||||
String lib = ir_gen.module.foreign_library_paths[i];
|
String lib = ir_gen.module.foreign_library_paths[i];
|
||||||
// gb_printf_err("Linking lib: %.*s\n", LIT(lib));
|
|
||||||
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
||||||
" \"%.*s\"", LIT(lib));
|
" \"%.*s\"", LIT(lib));
|
||||||
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
||||||
|
|||||||
+50
-15
@@ -999,11 +999,11 @@ Ast *ast_import_decl(AstFile *f, Token token, bool is_using, Token relpath, Toke
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast *ast_foreign_import_decl(AstFile *f, Token token, Token filepath, Token library_name,
|
Ast *ast_foreign_import_decl(AstFile *f, Token token, Array<Token> filepaths, Token library_name,
|
||||||
CommentGroup *docs, CommentGroup *comment) {
|
CommentGroup *docs, CommentGroup *comment) {
|
||||||
Ast *result = alloc_ast_node(f, Ast_ForeignImportDecl);
|
Ast *result = alloc_ast_node(f, Ast_ForeignImportDecl);
|
||||||
result->ForeignImportDecl.token = token;
|
result->ForeignImportDecl.token = token;
|
||||||
result->ForeignImportDecl.filepath = filepath;
|
result->ForeignImportDecl.filepaths = filepaths;
|
||||||
result->ForeignImportDecl.library_name = library_name;
|
result->ForeignImportDecl.library_name = library_name;
|
||||||
result->ForeignImportDecl.docs = docs;
|
result->ForeignImportDecl.docs = docs;
|
||||||
result->ForeignImportDecl.comment = comment;
|
result->ForeignImportDecl.comment = comment;
|
||||||
@@ -3491,15 +3491,38 @@ Ast *parse_foreign_decl(AstFile *f) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (is_blank_ident(lib_name)) {
|
if (is_blank_ident(lib_name)) {
|
||||||
syntax_error(lib_name, "Illegal foreign_library name: '_'");
|
syntax_error(lib_name, "Illegal foreign import name: '_'");
|
||||||
}
|
}
|
||||||
Token file_path = expect_token(f, Token_String);
|
Array<Token> filepaths = {};
|
||||||
Ast *s = nullptr;
|
if (allow_token(f, Token_OpenBrace)) {
|
||||||
if (f->curr_proc != nullptr) {
|
array_init(&filepaths, heap_allocator());
|
||||||
syntax_error(lib_name, "You cannot use foreign_library within a procedure. This must be done at the file scope");
|
|
||||||
s = ast_bad_decl(f, lib_name, file_path);
|
while (f->curr_token.kind != Token_CloseBrace &&
|
||||||
|
f->curr_token.kind != Token_EOF) {
|
||||||
|
|
||||||
|
Token path = expect_token(f, Token_String);
|
||||||
|
array_add(&filepaths, path);
|
||||||
|
|
||||||
|
if (!allow_token(f, Token_Comma)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_token(f, Token_CloseBrace);
|
||||||
} else {
|
} else {
|
||||||
s = ast_foreign_import_decl(f, token, file_path, lib_name, docs, f->line_comment);
|
filepaths = array_make<Token>(heap_allocator(), 0, 1);
|
||||||
|
Token path = expect_token(f, Token_String);
|
||||||
|
array_add(&filepaths, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ast *s = nullptr;
|
||||||
|
if (filepaths.count == 0) {
|
||||||
|
syntax_error(lib_name, "foreign import without any paths");
|
||||||
|
s = ast_bad_decl(f, lib_name, f->curr_token);
|
||||||
|
} else if (f->curr_proc != nullptr) {
|
||||||
|
syntax_error(lib_name, "You cannot use foreign import within a procedure. This must be done at the file scope");
|
||||||
|
s = ast_bad_decl(f, lib_name, filepaths[0]);
|
||||||
|
} else {
|
||||||
|
s = ast_foreign_import_decl(f, token, filepaths, lib_name, docs, f->line_comment);
|
||||||
}
|
}
|
||||||
expect_semicolon(f, s);
|
expect_semicolon(f, s);
|
||||||
return s;
|
return s;
|
||||||
@@ -4129,22 +4152,34 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<Ast *>
|
|||||||
} else if (node->kind == Ast_ForeignImportDecl) {
|
} else if (node->kind == Ast_ForeignImportDecl) {
|
||||||
ast_node(fl, ForeignImportDecl, node);
|
ast_node(fl, ForeignImportDecl, node);
|
||||||
|
|
||||||
String file_str = fl->filepath.string;
|
fl->fullpaths.allocator = heap_allocator();
|
||||||
fl->fullpath = file_str;
|
array_reserve(&fl->fullpaths, fl->filepaths.count);
|
||||||
|
|
||||||
|
for_array(fp_idx, fl->filepaths) {
|
||||||
|
String file_str = fl->filepaths[fp_idx].string;
|
||||||
|
String fullpath = file_str;
|
||||||
|
|
||||||
if (fl->collection_name != "system") {
|
|
||||||
String foreign_path = {};
|
String foreign_path = {};
|
||||||
bool ok = determine_path_from_string(p, node, base_dir, file_str, &foreign_path);
|
bool ok = determine_path_from_string(p, node, base_dir, file_str, &foreign_path);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
decls[i] = ast_bad_decl(f, fl->filepath, fl->filepath);
|
decls[i] = ast_bad_decl(f, fl->filepaths[fp_idx], fl->filepaths[fl->filepaths.count-1]);
|
||||||
continue;
|
goto end;
|
||||||
}
|
}
|
||||||
fl->fullpath = foreign_path;
|
fullpath = foreign_path;
|
||||||
|
array_add(&fl->fullpaths, fullpath);
|
||||||
}
|
}
|
||||||
|
if (fl->fullpaths.count == 0) {
|
||||||
|
error(decls[i], "No foreign paths found");
|
||||||
|
decls[i] = ast_bad_decl(f, fl->filepaths[0], fl->filepaths[fl->filepaths.count-1]);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (node->kind == Ast_WhenStmt) {
|
} else if (node->kind == Ast_WhenStmt) {
|
||||||
ast_node(ws, WhenStmt, node);
|
ast_node(ws, WhenStmt, node);
|
||||||
parse_setup_file_when_stmt(p, f, base_dir, ws);
|
parse_setup_file_when_stmt(p, f, base_dir, ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -391,10 +391,10 @@ AST_KIND(_DeclBegin, "", bool) \
|
|||||||
}) \
|
}) \
|
||||||
AST_KIND(ForeignImportDecl, "foreign import declaration", struct { \
|
AST_KIND(ForeignImportDecl, "foreign import declaration", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Token filepath; \
|
Array<Token> filepaths; \
|
||||||
Token library_name; \
|
Token library_name; \
|
||||||
String collection_name; \
|
String collection_name; \
|
||||||
String fullpath; \
|
Array<String> fullpaths; \
|
||||||
CommentGroup *docs; \
|
CommentGroup *docs; \
|
||||||
CommentGroup *comment; \
|
CommentGroup *comment; \
|
||||||
}) \
|
}) \
|
||||||
|
|||||||
Reference in New Issue
Block a user