/** * Loads an infusion into the virtual machine. * @param vm the virtual machine object to load the infusion into * @param di a di pointer to the infusion file in program space * @return a newly loaded infusion, or NULL in case of fail */ dj_infusion *dj_vm_loadInfusion(dj_vm *vm, dj_di_pointer di, dj_named_native_handler native_handlers[], unsigned char numHandlers) { int i; dj_infusion *infusion; dj_di_pointer element; dj_di_pointer staticFieldInfo = DJ_DI_NOT_SET; dj_di_pointer infusionList = DJ_DI_NOT_SET; dj_thread * thread; dj_global_id entryPoint; // iterate over the child elements, and find the static // field size info block. We need this info to allocate // the memory to hold the static fields for this // infusion for (i=0; i<dj_di_getListSize(di); i++) { element = dj_di_getListElement(di, i); switch (dj_di_element_getId(element)) { case STATICFIELDINFO: staticFieldInfo = element; break; case INFUSIONLIST: infusionList = element; break; } } // Check if each of the required elements were found if (staticFieldInfo==DJ_DI_NOT_SET||infusionList==DJ_DI_NOT_SET) dj_panic(DJ_PANIC_MALFORMED_INFUSION); // allocate the Infusion struct infusion = dj_infusion_create(staticFieldInfo, dj_di_infusionList_getSize(infusionList)); // if we're out of memory, let the caller handle it if (infusion==NULL) return NULL; // iterate over the child elements and get references // to the class list and method implementation list, // and get the header for (i=0; i<dj_di_getListSize(di); i++) { element = dj_di_getListElement(di, i); switch (dj_di_element_getId(element)) { case HEADER: infusion->header = element; break; case CLASSLIST: infusion->classList = element; break; case METHODIMPLLIST: infusion->methodImplementationList = element; break; case STRINGTABLE: infusion->stringTable = element; break; } } // Check if each of the required elements was found if (infusion->stringTable==DJ_DI_NOT_SET||infusion->classList==DJ_DI_NOT_SET||infusion->methodImplementationList==DJ_DI_NOT_SET||infusion->header==DJ_DI_NOT_SET) dj_panic(DJ_PANIC_MALFORMED_INFUSION); // iterate over the referenced infusion list and set the appropriate pointers for (i=0; i<dj_di_infusionList_getSize(infusionList); i++) { dj_di_pointer name = dj_di_infusionList_getChild(infusionList, i); dj_infusion *referenced_infusion = dj_vm_lookupInfusion(vm, name); if (infusion==NULL) dj_panic(DJ_PANIC_UNSATISFIED_LINK); infusion->referencedInfusions[i] = referenced_infusion; } // add the new infusion to the VM dj_vm_addInfusion(vm, infusion); // We're assuming here that base.di is the first file in the archive if (vm->systemInfusion == NULL) vm->systemInfusion = infusion; // This code was originally in load dj_vm_loadInfusionArchive. // Moved here because the application is not in an archive, but needs // some of the same code (not native_handlers, but class initialisers // and creating a thread) #ifdef DARJEELING_DEBUG char name[64]; dj_infusion_getName(infusion, name, 64); DEBUG_LOG(DBG_DARJEELING, "Loaded infusion %s.", name); #endif for (i=0; i<numHandlers; i++) { if (dj_di_strEqualsDirectStr(dj_di_header_getInfusionName(infusion->header), native_handlers[i].name)) { infusion->native_handler = native_handlers[i].handler; #ifdef DARJEELING_DEBUG DEBUG_LOG(DBG_DARJEELING, "Attached native handler to infusion %s.", name); #endif } } // run class initialisers for this infusion infusion = dj_vm_runClassInitialisers(vm, infusion); // find the entry point for the infusion if ((entryPoint.entity_id=dj_di_header_getEntryPoint(infusion->header))!=255) { // create a new thread and add it to the VM entryPoint.infusion = infusion; thread = dj_thread_create_and_run(entryPoint); if (thread==NULL) dj_panic(DJ_PANIC_OUT_OF_MEMORY); dj_vm_addThread(vm, thread); } return infusion; }
void dj_vm_loadInfusionArchive(dj_vm * vm, dj_archive* archive, dj_named_native_handler native_handlers[], unsigned char numHandlers) { dj_thread * thread; dj_infusion * infusion = NULL; dj_di_pointer archive_start = archive->start; dj_di_pointer archive_end = archive->end; unsigned char digit, i; dj_global_id entryPoint; unsigned long size, pos; bool first = true; // skip header, we'll just assume you're not passing something silly into this method archive_start += 8; while (archive_start<archive_end-1) { // read size size = 0; pos = AR_EHEADER_SIZE_START; while (((digit=dj_di_getU8(archive_start+pos))!=' ')&&(pos<AR_EHEADER_SIZE_END)) { size *= 10; size += digit - '0'; pos++; } // if filename starts with '/' skip this entry, since it's part of a // GNU extension on the common AR format if (dj_di_getU8(archive_start)!='/') { // Read infusion file. We're assuming here that base.di is the first file in the archive if (first) infusion = dj_vm_loadSystemInfusion(vm, archive_start + AR_EHEADER_SIZE); else infusion = dj_vm_loadInfusion(vm, archive_start + AR_EHEADER_SIZE); // If infusion is not loaded a critical error has occured if (infusion == NULL){ DARJEELING_PRINTF("Not enough space to create the infusion : %c%c%c%c%c%c%c%c\n", dj_di_getU8(archive_start+0), dj_di_getU8(archive_start+1), dj_di_getU8(archive_start+2), dj_di_getU8(archive_start+3), dj_di_getU8(archive_start+4), dj_di_getU8(archive_start+5), dj_di_getU8(archive_start+6), dj_di_getU8(archive_start+7) ); dj_panic(DJ_PANIC_OUT_OF_MEMORY); } /* else DARJEELING_PRINTF("[%s.di] %ld\n", (char *) dj_di_header_getInfusionName(infusion->header), size ); */ #ifdef DARJEELING_DEBUG char name[64]; dj_infusion_getName(infusion, name, 64); DEBUG_LOG("Loaded infusion %s.", name); #endif for (i=0; i<numHandlers; i++) { if (dj_di_strEqualsDirectStr(dj_di_header_getInfusionName(infusion->header), native_handlers[i].name)) { infusion->native_handler = native_handlers[i].handler; #ifdef DARJEELING_DEBUG DEBUG_LOG("Attached native handler to infusion %s.", name); #endif } } // run class initialisers for this infusion infusion = dj_vm_runClassInitialisers(vm, infusion); // find the entry point for the infusion if ((entryPoint.entity_id=dj_di_header_getEntryPoint(infusion->header))!=255) { // create a new thread and add it to the VM entryPoint.infusion = infusion; thread = dj_thread_create_and_run(entryPoint); if (thread==NULL) dj_panic(DJ_PANIC_OUT_OF_MEMORY); dj_vm_addThread(vm, thread); } first = false; } // files are 2-byte aligned if (size&1) size++; archive_start += size + AR_EHEADER_SIZE; } }