jm_status_enu_t fmi2_capi_free_dll(fmi2_capi_t* fmu)
{
	if (fmu == NULL) {
		return jm_status_error; /* Return without writing any log message */
	}

	if (fmu->dllHandle) {
		jm_status_enu_t status =
			(fmu->debugMode != 0) ?
                /* When running valgrind this may be convenient to track mem leaks */
                jm_status_success:
                jm_portability_free_dll_handle(fmu->dllHandle);
		fmu->dllHandle = 0;
		if (status == jm_status_error) { /* Free the library handle */
			jm_log(fmu->callbacks, FMI_CAPI_MODULE_NAME, jm_log_level_error, "Could not free the FMU binary: %s", jm_portability_get_last_dll_error());
			return jm_status_error;
		} else {
			jm_log_verbose(fmu->callbacks, FMI_CAPI_MODULE_NAME, "Successfully unloaded FMU binary");
			return jm_status_success;
		}
	}
	return jm_status_success;
}
/* Print msgIn into msgOut by expanding variable references of the form #<Type><VR># into variable names
  and replacing '##' with a single # */
void fmi1_import_expand_variable_references_impl(fmi1_import_t* fmu, const char* msgIn){
	jm_vector(char)* msgOut = &fmu->logMessageBuffer;
	fmi1_xml_model_description_t* md = fmu->md;
	jm_callbacks* callbacks = fmu->callbacks;
    char curCh;
	const char* firstRef;
    size_t i; /* next char index after curCh in msgIn*/ 
	size_t msgLen = strlen(msgIn)+1; /* original message length including terminating 0 */

	if(jm_vector_reserve(char)(msgOut, msgLen + 100) < msgLen + 100) {
		jm_log(fmu->callbacks,"LOGGER", jm_log_level_warning, "Could not allocate memory for the log message");
		jm_vector_resize(char)(msgOut, 6);
		memcpy(jm_vector_get_itemp(char)(msgOut,0),"ERROR",6); /* at least 16 chars are always there */
		return;
	}

	/* check if there are any refs at all and copy the head of the string without references */
	firstRef = strchr(msgIn, '#');
	if(firstRef) {
		i = firstRef - msgIn;
		jm_vector_resize(char)(msgOut, i);
		if(i) {
			memcpy(jm_vector_get_itemp(char)(msgOut, 0), msgIn, i);
		}
		curCh = msgIn[i++];
	}
	else {
		jm_vector_resize(char)(msgOut, msgLen);
		memcpy(jm_vector_get_itemp(char)(msgOut, 0), msgIn, msgLen);
		return;
	}
    do {
        if (curCh!='#') {
            jm_vector_push_back(char)(msgOut, curCh); /* copy in to out */
        }
		else if(msgIn[i] == '#') {
			jm_vector_push_back(char)(msgOut, '#');
			i++; /* skip the second # */
		}
		else {
			fmi1_value_reference_t vr = fmi1_undefined_value_reference;
			char typeChar = msgIn[i++];
			size_t pastePos = jm_vector_get_size(char)(msgOut);
			fmi1_base_type_enu_t baseType;
			size_t num_digits;
			fmi1_xml_variable_t* var;
			const char* name;
			size_t nameLen;
			switch(typeChar) {
				case 'r': 
					baseType = fmi1_base_type_real;
					break;
				case 'i': 
					baseType = fmi1_base_type_int;
					break;
				case 'b': 
					baseType = fmi1_base_type_bool;
					break;
				case 's': 
					baseType = fmi1_base_type_str;
					break;
				default:
					jm_vector_push_back(char)(msgOut, 0);
					jm_log(callbacks,"LOGGER", jm_log_level_warning, 
						"Expected type specification character 'r', 'i', 'b' or 's' in log message here: '%s'", 
					jm_vector_get_itemp(char)(msgOut,0));
                    jm_vector_resize(char)(msgOut, msgLen);
					memcpy(jm_vector_get_itemp(char)(msgOut,0),msgIn,msgLen);
					return;
			}
            curCh = msgIn[i++];
			while( isdigit(curCh) ) {
				jm_vector_push_back(char)(msgOut, curCh);
	            curCh = msgIn[i++];
			}
			num_digits = jm_vector_get_size(char)(msgOut) - pastePos;
			jm_vector_push_back(char)(msgOut, 0);
			if(num_digits == 0) {
				jm_log(callbacks,"LOGGER", jm_log_level_warning, "Expected value reference in log message here: '%s'", jm_vector_get_itemp(char)(msgOut,0));
                                jm_vector_resize(char)(msgOut, msgLen);
                jm_vector_resize(char)(msgOut, msgLen);
				memcpy(jm_vector_get_itemp(char)(msgOut,0),msgIn,msgLen);
				return;
			}
			else if(curCh != '#') {
				jm_log(callbacks,"LOGGER", jm_log_level_warning, "Expected terminating '#' in log message here: '%s'", jm_vector_get_itemp(char)(msgOut,0));
                                jm_vector_resize(char)(msgOut, msgLen);
                jm_vector_resize(char)(msgOut, msgLen);
				memcpy(jm_vector_get_itemp(char)(msgOut,0),msgIn,msgLen);
				return;
			}
			
			if(sscanf(jm_vector_get_itemp(char)(msgOut, pastePos), "%u",&vr) != 1) {
				jm_log(callbacks,"LOGGER", jm_log_level_warning, "Could not decode value reference in log message here: '%s'", jm_vector_get_itemp(char)(msgOut,0));
                                jm_vector_resize(char)(msgOut, msgLen);
                jm_vector_resize(char)(msgOut, msgLen);
				memcpy(jm_vector_get_itemp(char)(msgOut,0),msgIn,msgLen);
				return;
			}
			var = fmi1_xml_get_variable_by_vr(md,baseType,vr);
			if(!var) {
				jm_log(callbacks,"LOGGER", jm_log_level_warning, "Could not find variable referenced in log message here: '%s'", jm_vector_get_itemp(char)(msgOut,0));
                                jm_vector_resize(char)(msgOut, msgLen);
                jm_vector_resize(char)(msgOut, msgLen);
				memcpy(jm_vector_get_itemp(char)(msgOut,0),msgIn,msgLen);
				return;
			}
			name = fmi1_xml_get_variable_name(var);
			nameLen = strlen(name);
			if(jm_vector_resize(char)(msgOut, pastePos + nameLen) != pastePos + nameLen) {
				jm_log(callbacks,"LOGGER", jm_log_level_warning, "Could not allocate memory for the log message");
                                jm_vector_resize(char)(msgOut, msgLen);
                jm_vector_resize(char)(msgOut, msgLen);
				memcpy(jm_vector_get_itemp(char)(msgOut,0),msgIn,msgLen);
				return;
			};
			memcpy(jm_vector_get_itemp(char)(msgOut, pastePos), name, nameLen);
        }
        curCh = msgIn[i++];
    } while (curCh);
    jm_vector_push_back(char)(msgOut, 0);
}