void non_required_module_is_not_visible() { World* world = global_world(); test_write_fake_file("module_a.ca", 1, "a = 1"); test_write_fake_file("module_b.ca", 1, "b = 1"); Block* module_a = load_module_file(world, temp_string("module_a"), "module_a.ca"); Block* module_b = load_module_file(world, temp_string("module_b"), "module_b.ca"); test_assert(find_name(module_a, "a") != NULL); test_assert(find_name(module_b, "a") == NULL); }
void file_watch_trigger_actions(World* world, FileWatch* watch) { // Walk through each action and execute it. for (int i = 0; i < list_length(&watch->onChangeActions); i++) { caValue* action = list_get(&watch->onChangeActions, i); Name label = as_int(list_get(action, 0)); ca_assert(label != name_None); switch (label) { case name_NativePatch: { caValue* moduleName = list_get(action, 1); NativePatch* nativeModule = add_native_patch(world, as_cstring(moduleName)); native_patch_load_from_file(nativeModule, as_cstring(&watch->filename)); native_patch_finish_change(nativeModule); break; } case name_PatchBlock: { // Reload this code block. caValue* moduleName = list_get(action, 1); load_module_file(world, as_cstring(moduleName), as_cstring(&watch->filename)); break; } default: internal_error("unrecognized file watch action"); } } }
void source_file_location() { test_write_fake_file("block.ca", 1, "a = 1"); Block* block = load_module_file(global_world(), temp_string("source_file_location"), "block.ca"); test_equals(block_get_source_filename(block), "block.ca"); }
void type_name_visible_from_module() { FakeFilesystem fs; fs.set("a", "type A { int i }"); load_module_file(global_world(), "a", "a"); fs.set("b", "require a\ntest_spy(make(A))"); Block* b = load_module_file(global_world(), "b", "b"); Stack stack; push_frame(&stack, b); test_spy_clear(); run_interpreter(&stack); test_assert(&stack); test_equals(test_spy_get_results(), "[{i: 0}]"); }
// Attempt to load a module file. // If file found and is a valid module, then load into memory, relocate and link to CHDK core // Returns memory address of module if successful, 0 if failure. flat_hdr* module_preload(const char *path, const char *name, _version_t ver) { // Allocate buffer and open file int module_fd = b_open(path); if (module_fd <= 0) { moduleload_error(name, "open error"); return 0; } // Read module header only to get size info flat_hdr flat; b_read(module_fd, (char*)&flat, sizeof(flat)); // TODO - compare loaded with requested size // Error message char *msg = 0; // Pointer to memory allocated to load module flat_hdr* flat_buf = 0; // Check version and magic number - make sure it is a CHDK module file if ((flat.rev == FLAT_VERSION) && (flat.magic == FLAT_MAGIC_NUMBER)) { // Allocate module memory, and load module code msg = load_module_file(module_fd, name, flat.reloc_start, flat.bss_size, &flat_buf); if (msg == 0) { // Module info checks ModuleInfo *mod_info = flat_buf->_module_info = (ModuleInfo*)((unsigned int)flat_buf+flat_buf->_module_info_offset); // Validate version requirements msg = validate(mod_info, ver); if (msg == 0) { // Make relocations msg = link_module(module_fd, flat_buf); } } } else msg = "bad magicnum"; // Close file b_close(module_fd); // If any error found, free module memory and display error if (msg) { if (flat_buf) free(flat_buf); moduleload_error(name, msg); return 0; } // TODO these could be changed to operate on affected address ranges only // after relocating but before attempting to execute loaded code // clean data cache to ensure code is in main memory dcache_clean_all(); // then flush instruction cache to ensure no addresses containing new code are cached icache_flush_all(); // Return module memory address return flat_buf; }