2 Copyright (C) 2012 Modelon AB
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the BSD style license.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 FMILIB_License.txt file for more details.
12 You should have received a copy of the FMILIB_License.txt file
13 along with this program. If not, contact Modelon AB <http://www.modelon.com>.
19 #include <JM/jm_vector.h>
21 #include "fmi1_xml_parser.h"
22 #include "fmi1_xml_type_impl.h"
23 #include "fmi1_xml_model_description_impl.h"
25 #include "fmi1_xml_variable_impl.h"
27 static const char* module = "FMI1XML";
29 const char* fmi1_xml_get_variable_name(fmi1_xml_variable_t* v) {
33 const char* fmi1_xml_get_variable_description(fmi1_xml_variable_t* v) {
34 return v->description;
37 size_t fmi1_xml_get_variable_original_order(fmi1_xml_variable_t* v) {
38 return v->originalIndex;
41 fmi1_value_reference_t fmi1_xml_get_variable_vr(fmi1_xml_variable_t* v) {
45 fmi1_variable_alias_kind_enu_t fmi1_xml_get_variable_alias_kind(fmi1_xml_variable_t* v) {
46 return (fmi1_variable_alias_kind_enu_t)v->aliasKind;
49 fmi1_xml_variable_t* fmi1_xml_get_variable_alias_base(fmi1_xml_model_description_t* md, fmi1_xml_variable_t* v) {
50 fmi1_xml_variable_t key;
51 fmi1_xml_variable_t *pkey = &key, *base;
53 if(!md->variablesByVR) return 0;
54 if(v->aliasKind == fmi1_variable_is_not_alias) return v;
56 key.aliasKind = fmi1_variable_is_not_alias;
58 found = jm_vector_bsearch(jm_voidp)(md->variablesByVR,(void**)&pkey, fmi1_xml_compare_vr);
65 Return the list of all the variables aliased to the given one (including the base one.
66 The list is ordered: base variable, aliases, negated aliases.
68 jm_status_enu_t fmi1_xml_get_variable_aliases(fmi1_xml_model_description_t* md,fmi1_xml_variable_t* v, jm_vector(jm_voidp)* list) {
69 fmi1_xml_variable_t key, *cur;
70 fmi1_value_reference_t vr = fmi1_xml_get_variable_vr(v);
71 size_t baseIndex, i, num = jm_vector_get_size(jm_voidp)(md->variablesByVR);
75 baseIndex = jm_vector_bsearch_index(jm_voidp)(md->variablesByVR,(void**)&cur, fmi1_xml_compare_vr);
76 cur = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(md->variablesByVR, baseIndex);
79 while(fmi1_xml_get_variable_vr(cur) == vr) {
80 if(!jm_vector_push_back(jm_voidp)(list, cur)) {
81 jm_log_fatal(md->callbacks,module,"Could not allocate memory");
82 return jm_status_error;
85 cur = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(md->variablesByVR, i);
91 cur = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(md->variablesByVR, i);
92 while(fmi1_xml_get_variable_vr(cur) == vr) {
93 if(!jm_vector_push_back(jm_voidp)(list, cur)) {
94 jm_log_fatal(md->callbacks,module,"Could not allocate memory");
95 return jm_status_error;
99 cur = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(md->variablesByVR, i - 1);
103 return jm_status_success;
107 fmi1_xml_variable_typedef_t* fmi1_xml_get_variable_declared_type(fmi1_xml_variable_t* v) {
108 return (fmi1_xml_variable_typedef_t*)(fmi1_xml_find_type_struct(v->typeBase, fmi1_xml_type_struct_enu_typedef));
111 fmi1_base_type_enu_t fmi1_xml_get_variable_base_type(fmi1_xml_variable_t* v) {
112 fmi1_xml_variable_type_base_t* type = v->typeBase;
113 type = fmi1_xml_find_type_struct(type, fmi1_xml_type_struct_enu_base);
114 return (type->baseType);
117 int fmi1_xml_get_variable_has_start(fmi1_xml_variable_t* v) {
118 return (v->typeBase->structKind == fmi1_xml_type_struct_enu_start);
121 int fmi1_xml_get_variable_is_fixed(fmi1_xml_variable_t* v) {
122 fmi1_xml_variable_type_base_t* type = v->typeBase;
123 return ((type->structKind == fmi1_xml_type_struct_enu_start) && (type->isFixed));
126 fmi1_variability_enu_t fmi1_xml_get_variability(fmi1_xml_variable_t* v) {
127 return (fmi1_variability_enu_t)v->variability;
130 fmi1_causality_enu_t fmi1_xml_get_causality(fmi1_xml_variable_t* v) {
131 return (fmi1_causality_enu_t)v->causality;
134 double fmi1_xml_get_real_variable_start(fmi1_xml_real_variable_t* v) {
135 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
136 if(fmi1_xml_get_variable_has_start(vv)) {
137 fmi1_xml_variable_start_real_t* start = (fmi1_xml_variable_start_real_t*)(vv->typeBase);
140 return fmi1_xml_get_real_variable_nominal(v);
143 fmi1_xml_unit_t* fmi1_xml_get_real_variable_unit(fmi1_xml_real_variable_t* v) {
144 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
145 fmi1_xml_real_type_props_t* props = (fmi1_xml_real_type_props_t*)(fmi1_xml_find_type_struct(vv->typeBase, fmi1_xml_type_struct_enu_props));
146 if(!props || !props->displayUnit) return 0;
147 return props->displayUnit->baseUnit;
150 fmi1_xml_display_unit_t* fmi1_xml_get_real_variable_display_unit(fmi1_xml_real_variable_t* v) {
151 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
152 fmi1_xml_real_type_props_t* props = (fmi1_xml_real_type_props_t*)(fmi1_xml_find_type_struct(vv->typeBase, fmi1_xml_type_struct_enu_props));
153 if(!props || !props->displayUnit || !props->displayUnit->displayUnit[0]) return 0;
154 return props->displayUnit;
157 double fmi1_xml_get_real_variable_max(fmi1_xml_real_variable_t* v) {
158 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
159 fmi1_xml_real_type_props_t* props = (fmi1_xml_real_type_props_t*)(fmi1_xml_find_type_props(vv->typeBase));
161 return props->typeMax;
164 double fmi1_xml_get_real_variable_min(fmi1_xml_real_variable_t* v) {
165 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
166 fmi1_xml_real_type_props_t* props = (fmi1_xml_real_type_props_t*)(fmi1_xml_find_type_props(vv->typeBase));
168 return props->typeMin;
171 double fmi1_xml_get_real_variable_nominal(fmi1_xml_real_variable_t* v){
172 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
173 fmi1_xml_real_type_props_t* props = (fmi1_xml_real_type_props_t*)(fmi1_xml_find_type_props(vv->typeBase));
175 return props->typeNominal;
178 int fmi1_xml_get_integer_variable_start(fmi1_xml_integer_variable_t* v){
179 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
180 if(fmi1_xml_get_variable_has_start(vv)) {
181 fmi1_xml_variable_start_integer_t* start = (fmi1_xml_variable_start_integer_t*)(vv->typeBase);
187 int fmi1_xml_get_integer_variable_min(fmi1_xml_integer_variable_t* v){
188 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
189 fmi1_xml_integer_type_props_t* props = (fmi1_xml_integer_type_props_t*)(fmi1_xml_find_type_props(vv->typeBase));
191 return props->typeMin;
194 int fmi1_xml_get_integer_variable_max(fmi1_xml_integer_variable_t* v){
195 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
196 fmi1_xml_integer_type_props_t* props = (fmi1_xml_integer_type_props_t*)(fmi1_xml_find_type_props(vv->typeBase));
198 return props->typeMax;
201 int fmi1_xml_get_enum_variable_min(fmi1_xml_enum_variable_t* v){
202 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
203 fmi1_xml_enum_type_props_t* props = (fmi1_xml_enum_type_props_t*)(fmi1_xml_find_type_props(vv->typeBase));
205 return props->typeMin;
208 int fmi1_xml_get_enum_variable_max(fmi1_xml_enum_variable_t* v){
209 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
210 fmi1_xml_enum_type_props_t* props = (fmi1_xml_enum_type_props_t*)(fmi1_xml_find_type_props(vv->typeBase));
212 return props->typeMax;
215 const char* fmi1_xml_get_string_variable_start(fmi1_xml_string_variable_t* v){
216 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
217 if(fmi1_xml_get_variable_has_start(vv)) {
218 fmi1_xml_variable_start_string_t* start = (fmi1_xml_variable_start_string_t*)(vv->typeBase);
224 int fmi1_xml_get_enum_variable_start(fmi1_xml_enum_variable_t* v) {
225 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
226 if(fmi1_xml_get_variable_has_start(vv)) {
227 fmi1_xml_variable_start_integer_t* start = (fmi1_xml_variable_start_integer_t*)(vv->typeBase);
233 fmi1_boolean_t fmi1_xml_get_boolean_variable_start(fmi1_xml_bool_variable_t* v) {
234 fmi1_xml_variable_t* vv = (fmi1_xml_variable_t*)v;
235 if(fmi1_xml_get_variable_has_start(vv)) {
236 fmi1_xml_variable_start_integer_t* start = (fmi1_xml_variable_start_integer_t*)(vv->typeBase);
242 size_t fmi1_xml_get_direct_dependency_size(fmi1_xml_model_description_t* md,fmi1_xml_variable_t*v) {
243 if(v->directDependency) {
244 return jm_vector_get_size(jm_voidp)(v->directDependency);
247 return jm_vector_get_size(jm_voidp)(md->inputVariables);
251 /* DirectDependency is returned for variables with causality Output. Null pointer for others. */
252 jm_status_enu_t fmi1_xml_get_direct_dependency(fmi1_xml_model_description_t* md, fmi1_xml_variable_t* v, jm_vector(jm_voidp)* list) {
254 if(fmi1_xml_get_causality(v) != fmi1_causality_enu_output) return jm_status_error;
255 jm_vector_resize(jm_voidp)(list, 0);
256 if(v->directDependency) {
257 size = jm_vector_get_size(jm_voidp)(v->directDependency);
258 if(jm_vector_reserve(jm_voidp)(list, size) < size) return jm_status_error;
259 jm_vector_copy(jm_voidp)(list,v->directDependency);
261 /*no direct dependency defined, deliver all inputs, see FMI for ME spec. p 38.*/
263 if (md->inputVariables){
264 jm_vector_copy(jm_voidp)(list,md->inputVariables);
267 jm_log_error(md->callbacks,module, "List of input variables not found.");
270 return jm_status_success;
273 fmi1_xml_real_variable_t* fmi1_xml_get_variable_as_real(fmi1_xml_variable_t* v) {
274 if(fmi1_xml_get_variable_base_type(v) == fmi1_base_type_real) return (void*)v;
278 fmi1_xml_integer_variable_t* fmi1_xml_get_variable_as_integer(fmi1_xml_variable_t*v){
279 if(fmi1_xml_get_variable_base_type(v) == fmi1_base_type_int) return (void*)v;
282 fmi1_xml_enum_variable_t* fmi1_xml_get_variable_as_enum(fmi1_xml_variable_t* v){
283 if(fmi1_xml_get_variable_base_type(v) == fmi1_base_type_enum) return (void*)v;
286 fmi1_xml_string_variable_t* fmi1_xml_get_variable_as_string(fmi1_xml_variable_t* v){
287 if(fmi1_xml_get_variable_base_type(v) == fmi1_base_type_str) return (void*)v;
290 fmi1_xml_bool_variable_t* fmi1_xml_get_variable_as_boolean(fmi1_xml_variable_t* v){
291 if(fmi1_xml_get_variable_base_type(v) == fmi1_base_type_bool) return (void*)v;
295 void fmi1_xml_free_direct_dependencies(jm_named_ptr named) {
296 fmi1_xml_variable_t* v = named.ptr;
297 if(v->directDependency) {
298 jm_vector_free(jm_voidp)(v->directDependency);
299 v->directDependency = 0;
303 int fmi1_xml_handle_ScalarVariable(fmi1_xml_parser_context_t *context, const char* data) {
305 fmi1_xml_model_description_t* md = context->modelDescription;
306 fmi1_xml_variable_t* variable;
307 fmi1_xml_variable_t dummyV;
308 const char* description = 0;
309 jm_named_ptr named, *pnamed;
310 jm_vector(char)* bufName = fmi1_xml_reserve_parse_buffer(context,1,100);
311 jm_vector(char)* bufDescr = fmi1_xml_reserve_parse_buffer(context,2,100);
314 if(!bufName || !bufDescr) return -1;
316 /* <xs:attribute name="valueReference" type="xs:unsignedInt" use="required"> */
317 if(fmi1_xml_set_attr_uint(context, fmi1_xml_elmID_ScalarVariable, fmi_attr_id_valueReference, 1, &vr, 0)) return -1;
319 if(vr == fmi1_undefined_value_reference) {
320 context->skipOneVariableFlag = 1;
324 /* <xs:attribute name="name" type="xs:normalizedString" use="required"/> */
325 fmi1_xml_set_attr_string(context, fmi1_xml_elmID_ScalarVariable, fmi_attr_id_name, 1, bufName) ||
326 /* <xs:attribute name="description" type="xs:string"/> */
327 fmi1_xml_set_attr_string(context, fmi1_xml_elmID_ScalarVariable, fmi_attr_id_description, 0, bufDescr)
330 if(context->skipOneVariableFlag) {
331 jm_log_error(context->callbacks,module, "Ignoring variable with undefined vr '%s'", jm_vector_get_itemp(char)(bufName,0));
334 if(jm_vector_get_size(char)(bufDescr)) {
335 description = jm_string_set_put(&md->descriptions, jm_vector_get_itemp(char)(bufDescr,0));
340 pnamed = jm_vector_push_back(jm_named_ptr)(&md->variablesByName, named);
342 if(pnamed) *pnamed = named = jm_named_alloc_v(bufName,sizeof(fmi1_xml_variable_t), dummyV.name - (char*)&dummyV, context->callbacks);
343 variable = named.ptr;
344 if( !pnamed || !variable ) {
345 fmi1_xml_parse_fatal(context, "Could not allocate memory");
349 variable->description = description;
350 variable->typeBase = 0;
351 variable->directDependency = 0;
352 variable->originalIndex = jm_vector_get_size(jm_named_ptr)(&md->variablesByName) - 1;
355 jm_name_ID_map_t variabilityConventionMap[] = {{"continuous",fmi1_variability_enu_continuous},
356 {"constant", fmi1_variability_enu_constant},
357 {"parameter", fmi1_variability_enu_parameter},
358 {"discrete", fmi1_variability_enu_discrete},{0,0}};
359 unsigned int variability;
360 /* <xs:attribute name="variability" default="continuous"> */
361 if(fmi1_xml_set_attr_enum(context, fmi1_xml_elmID_ScalarVariable, fmi_attr_id_variability,0,&variability,fmi1_variability_enu_continuous,variabilityConventionMap))
363 variable->variability = variability;
366 jm_name_ID_map_t causalityConventionMap[] = {{"internal",fmi1_causality_enu_internal},
367 {"input",fmi1_causality_enu_input},
368 {"output",fmi1_causality_enu_output},
369 {"none",fmi1_causality_enu_none},{0,0}};
370 /* <xs:attribute name="causality" default="internal"> */
371 unsigned int causality;
372 if(fmi1_xml_set_attr_enum(context, fmi1_xml_elmID_ScalarVariable, fmi_attr_id_causality,0,&causality,fmi1_causality_enu_internal,causalityConventionMap))
374 variable->causality = causality;
377 jm_name_ID_map_t aliasConventionMap[] = {{"alias", 1},
379 {"noAlias", 0}, {0,0}};
381 /* <xs:attribute name="alias" default="noAlias"> */
382 if(fmi1_xml_set_attr_enum(context, fmi1_xml_elmID_ScalarVariable, fmi_attr_id_alias ,0,&alias,0,aliasConventionMap))
384 if(alias == 0) variable->aliasKind = fmi1_variable_is_not_alias;
385 else if (alias == 1) variable->aliasKind = fmi1_variable_is_alias;
386 else if (alias == 2) variable->aliasKind = fmi1_variable_is_negated_alias;
391 if(context->skipOneVariableFlag) {
392 context->skipOneVariableFlag = 0;
395 /* check that the type for the variable is set */
396 fmi1_xml_model_description_t* md = context->modelDescription;
397 fmi1_xml_variable_t* variable = jm_vector_get_last(jm_named_ptr)(&md->variablesByName).ptr;
398 if(!variable->typeBase) {
399 jm_log_error(context->callbacks, module, "No variable type element for variable %s. Assuming Real.", variable->name);
401 return fmi1_xml_handle_Real(context, data);
404 /* might give out a warning if(data[0] != 0) */
410 int fmi1_xml_handle_DirectDependency(fmi1_xml_parser_context_t *context, const char* data) {
411 if(context->skipOneVariableFlag) return 0;
413 fmi1_xml_model_description_t* md = context->modelDescription;
414 fmi1_xml_variable_t* variable = jm_vector_get_last(jm_named_ptr)(&md->variablesByName).ptr;
415 if(variable->causality != fmi1_causality_enu_output) {
416 jm_log_error(context->callbacks,module,
417 "DirectDependency XML element cannot be defined for '%s' since causality is not output. Skipping.", variable->name);
418 context->skipElementCnt = 1;
423 fmi1_xml_model_description_t* md = context->modelDescription;
424 fmi1_xml_variable_t* variable = jm_vector_get_last(jm_named_ptr)(&md->variablesByName).ptr;
426 - always create the list to be able to differentiate no depedendencies from all dependencies (no DirectDependency element present)
427 if(jm_vector_get_size(jm_voidp)(&context->directDependencyBuf))
430 variable->directDependency = jm_vector_clone(jm_voidp)(&context->directDependencyBuf);
431 if(!variable->directDependency) {
432 fmi1_xml_parse_fatal(context, "Could not allocate memory");
436 jm_vector_resize(jm_voidp)(&context->directDependencyBuf,0);
441 int fmi1_xml_handle_Name(fmi1_xml_parser_context_t *context, const char* data) {
442 if(context->skipOneVariableFlag) return 0;
448 fmi1_xml_model_description_t* md = context->modelDescription;
449 fmi1_xml_variable_t* variable = jm_vector_get_last(jm_named_ptr)(&md->variablesByName).ptr;
450 size_t namelen = strlen(data), i = 0, j;
454 #define TRIM_SPACE " \n\r\t"
456 while(strchr(TRIM_SPACE, data[i])) i++;
457 while(strchr(TRIM_SPACE, data[namelen-1])) namelen--;
460 jm_log_error(context->callbacks, module,
461 "Unexpected empty Name element for DirectDependency of variable %s. Ignoring.", variable->name);
464 namep = jm_vector_push_back(jm_string)(&context->directDependencyStringsStore, name);
465 if(namep) *namep = name = context->callbacks->malloc(namelen + 1);
466 itemp = jm_vector_push_back(jm_voidp)(&context->directDependencyBuf, name);
467 if(!namep || !itemp || !name) {
468 fmi1_xml_parse_fatal(context, "Could not allocate memory");
471 for(j = 0; i<namelen;i++) {
479 static void fmi1_log_error_if_start_required(
480 fmi1_xml_parser_context_t *context,
481 fmi1_xml_variable_t *variable)
483 if (fmi1_xml_is_attr_defined(context, fmi_attr_id_fixed)) {
484 jm_log_error(context->callbacks, module,
485 "Error: variable %s: 'fixed' attributed is only allowed when start is defined",
488 } else if (variable->causality == fmi1_causality_enu_input) {
489 jm_log_error(context->callbacks, module,
490 "Error: variable %s: start value required for input variables",
495 int fmi1_xml_handle_Real(fmi1_xml_parser_context_t *context, const char* data) {
496 fmi1_xml_model_description_t* md = context->modelDescription;
497 fmi1_xml_variable_t* variable = jm_vector_get_last(jm_named_ptr)(&md->variablesByName).ptr;
498 fmi1_xml_type_definitions_t* td = &md->typeDefinitions;
499 fmi1_xml_variable_type_base_t * declaredType = 0;
500 fmi1_xml_real_type_props_t * type = 0;
503 if(context->skipOneVariableFlag){
506 /* don't do anything. might give out a warning if(data[0] != 0) */
509 assert(!variable->typeBase);
511 declaredType = fmi1_get_declared_type(context, fmi1_xml_elmID_Real, &td->defaultRealType.typeBase);
513 if(!declaredType) return -1;
516 int hasUnit = fmi1_xml_is_attr_defined(context, fmi_attr_id_unit) ||
517 fmi1_xml_is_attr_defined(context, fmi_attr_id_displayUnit);
518 int hasMin = fmi1_xml_is_attr_defined(context, fmi_attr_id_min);
519 int hasMax = fmi1_xml_is_attr_defined(context, fmi_attr_id_max);
520 int hasNom = fmi1_xml_is_attr_defined(context, fmi_attr_id_nominal);
521 int hasQuan = fmi1_xml_is_attr_defined(context, fmi_attr_id_quantity);
522 int hasRelQ = fmi1_xml_is_attr_defined(context, fmi_attr_id_relativeQuantity);
525 if(hasUnit || hasMin || hasMax || hasNom || hasQuan || hasRelQ) {
526 fmi1_xml_real_type_props_t* props = 0;
528 if(declaredType->structKind == fmi1_xml_type_struct_enu_typedef)
529 props = (fmi1_xml_real_type_props_t*)(declaredType->baseTypeStruct);
531 props = (fmi1_xml_real_type_props_t* )declaredType;
533 fmi1_xml_reserve_parse_buffer(context, 1, 0);
534 fmi1_xml_reserve_parse_buffer(context, 2, 0);
536 type = fmi1_xml_parse_real_type_properties(context, fmi1_xml_elmID_Real);
539 type->typeBase.baseTypeStruct = declaredType;
540 if( !hasUnit) type->displayUnit = props->displayUnit;
541 if( !hasMin) type->typeMin = props->typeMin;
542 if( !hasMax) type->typeMax = props->typeMax;
543 if( !hasNom) type->typeNominal = props->typeNominal;
544 if( !hasQuan) type->quantity = props->quantity;
545 if( !hasRelQ) type->typeBase.relativeQuantity = props->typeBase.relativeQuantity;
548 type = (fmi1_xml_real_type_props_t*)declaredType;
550 variable->typeBase = &type->typeBase;
552 hasStart = fmi1_xml_is_attr_defined(context, fmi_attr_id_start);
554 fmi1_xml_variable_start_real_t * start = (fmi1_xml_variable_start_real_t*)fmi1_xml_alloc_variable_type_start(td, &type->typeBase, sizeof(fmi1_xml_variable_start_real_t));
557 fmi1_xml_parse_fatal(context, "Could not allocate memory");
561 /* <xs:attribute name="start" type="xs:double"/> */
562 fmi1_xml_set_attr_double(context, fmi1_xml_elmID_Real, fmi_attr_id_start, 0, &start->start, 0) ||
563 /* <xs:attribute name="fixed" type="xs:boolean"> */
564 fmi1_xml_set_attr_boolean(context, fmi1_xml_elmID_Real, fmi_attr_id_fixed, 0, &(isFixedBuf), 1)
567 start->typeBase.isFixed = isFixedBuf;
568 variable->typeBase = &start->typeBase;
570 fmi1_log_error_if_start_required(context, variable);
576 int fmi1_xml_handle_Integer(fmi1_xml_parser_context_t *context, const char* data) {
577 fmi1_xml_model_description_t* md = context->modelDescription;
578 fmi1_xml_type_definitions_t* td = &md->typeDefinitions;
579 fmi1_xml_variable_t* variable = jm_vector_get_last(jm_named_ptr)(&md->variablesByName).ptr;
580 fmi1_xml_variable_type_base_t * declaredType = 0;
581 fmi1_xml_integer_type_props_t * type = 0;
584 if (context->skipOneVariableFlag) {
587 /* don't do anything. might give out a warning if(data[0] != 0) */
591 declaredType = fmi1_get_declared_type(context, fmi1_xml_elmID_Integer,&td->defaultIntegerType.typeBase) ;
593 if(!declaredType) return -1;
596 int hasQuan = fmi1_xml_is_attr_defined(context, fmi_attr_id_quantity);
597 int hasMin = fmi1_xml_is_attr_defined(context, fmi_attr_id_min);
598 int hasMax = fmi1_xml_is_attr_defined(context, fmi_attr_id_max);
600 if(hasQuan ||hasMin || hasMax) {
601 fmi1_xml_integer_type_props_t* props = 0;
603 if(declaredType->structKind != fmi1_xml_type_struct_enu_typedef)
604 props = (fmi1_xml_integer_type_props_t*)declaredType;
606 props = (fmi1_xml_integer_type_props_t*)(declaredType->baseTypeStruct);
607 assert((props->typeBase.structKind == fmi1_xml_type_struct_enu_props) || (props->typeBase.structKind == fmi1_xml_type_struct_enu_base));
608 fmi1_xml_reserve_parse_buffer(context, 1, 0);
609 fmi1_xml_reserve_parse_buffer(context, 2, 0);
610 type = fmi1_xml_parse_integer_type_properties(context, fmi1_xml_elmID_Integer);
612 type->typeBase.baseTypeStruct = declaredType;
613 if(!hasMin) type->typeMin = props->typeMin;
614 if(!hasMax) type->typeMax = props->typeMax;
615 if(!hasQuan) type->quantity = props->quantity;
618 type = (fmi1_xml_integer_type_props_t*)declaredType;
620 variable->typeBase = &type->typeBase;
622 hasStart = fmi1_xml_is_attr_defined(context,fmi_attr_id_start);
624 fmi1_xml_variable_start_integer_t * start = (fmi1_xml_variable_start_integer_t*)fmi1_xml_alloc_variable_type_start(td, &type->typeBase, sizeof(fmi1_xml_variable_start_integer_t));
627 fmi1_xml_parse_fatal(context, "Could not allocate memory");
631 /* <xs:attribute name="start" type="xs:integer"/> */
632 fmi1_xml_set_attr_int(context, fmi1_xml_elmID_Integer, fmi_attr_id_start, 0, &start->start, 0);
633 /* <xs:attribute name="fixed" type="xs:boolean"> */
634 fmi1_xml_set_attr_boolean(context, fmi1_xml_elmID_Integer, fmi_attr_id_fixed, 0, &isFixedBuf, 1);
636 start->typeBase.isFixed = isFixedBuf;
637 variable->typeBase = &start->typeBase;
639 fmi1_log_error_if_start_required(context, variable);
645 int fmi1_xml_handle_Boolean(fmi1_xml_parser_context_t *context, const char* data) {
646 fmi1_xml_model_description_t* md = context->modelDescription;
647 fmi1_xml_type_definitions_t* td = &md->typeDefinitions;
648 fmi1_xml_variable_t* variable = jm_vector_get_last(jm_named_ptr)(&md->variablesByName).ptr;
651 if (context->skipOneVariableFlag) {
654 /* don't do anything. might give out a warning if(data[0] != 0) */
658 assert(!variable->typeBase);
660 variable->typeBase = fmi1_get_declared_type(context, fmi1_xml_elmID_Boolean, &td->defaultBooleanType) ;
662 if(!variable->typeBase) return -1;
664 hasStart = fmi1_xml_is_attr_defined(context,fmi_attr_id_start);
667 fmi1_xml_variable_start_integer_t * start = (fmi1_xml_variable_start_integer_t*)fmi1_xml_alloc_variable_type_start(td, variable->typeBase, sizeof(fmi1_xml_variable_start_integer_t ));
669 fmi1_xml_parse_fatal(context, "Could not allocate memory");
673 /* <xs:attribute name="start" type="xs:boolean"/> */
674 fmi1_xml_set_attr_boolean(context, fmi1_xml_elmID_Boolean, fmi_attr_id_start, 0, (int*)&start->start, 0) ||
675 /* <xs:attribute name="fixed" type="xs:boolean"> */
676 fmi1_xml_set_attr_boolean(context, fmi1_xml_elmID_Boolean, fmi_attr_id_fixed, 0, &isFixedBuf, 1)
679 start->typeBase.isFixed = isFixedBuf;
680 variable->typeBase = &start->typeBase;
682 fmi1_log_error_if_start_required(context, variable);
688 int fmi1_xml_handle_String(fmi1_xml_parser_context_t *context, const char* data) {
689 fmi1_xml_model_description_t* md = context->modelDescription;
690 fmi1_xml_type_definitions_t* td = &md->typeDefinitions;
691 fmi1_xml_variable_t* variable = jm_vector_get_last(jm_named_ptr)(&md->variablesByName).ptr;
694 if (context->skipOneVariableFlag) {
697 /* don't do anything. might give out a warning if(data[0] != 0) */
701 assert(!variable->typeBase);
703 variable->typeBase = fmi1_get_declared_type(context, fmi1_xml_elmID_String,&td->defaultStringType) ;
705 if(!variable->typeBase) return -1;
707 hasStart = fmi1_xml_is_attr_defined(context,fmi_attr_id_start);
709 jm_vector(char)* bufStartStr = fmi1_xml_reserve_parse_buffer(context,1, 100);
712 fmi1_xml_variable_start_string_t * start;
714 /* <xs:attribute name="start" type="xs:string"/> */
715 fmi1_xml_set_attr_string(context, fmi1_xml_elmID_String, fmi_attr_id_start, 0, bufStartStr) ||
716 /* <xs:attribute name="fixed" type="xs:boolean"> */
717 fmi1_xml_set_attr_boolean(context, fmi1_xml_elmID_Boolean, fmi_attr_id_fixed, 0, &isFixed, 1)
720 strlen = jm_vector_get_size_char(bufStartStr);
722 start = (fmi1_xml_variable_start_string_t*)fmi1_xml_alloc_variable_type_start(td, variable->typeBase, sizeof(fmi1_xml_variable_start_string_t) + strlen);
725 fmi1_xml_parse_fatal(context, "Could not allocate memory");
728 if (strlen != 0) { /* No need to memcpy empty strings (gives assetion error) */
729 memcpy(start->start, jm_vector_get_itemp_char(bufStartStr,0), strlen);
731 start->start[strlen] = 0;
732 variable->typeBase = &start->typeBase;
734 fmi1_log_error_if_start_required(context, variable);
740 int fmi1_xml_handle_Enumeration(fmi1_xml_parser_context_t *context, const char* data) {
742 fmi1_xml_model_description_t* md = context->modelDescription;
743 fmi1_xml_type_definitions_t* td = &md->typeDefinitions;
744 fmi1_xml_variable_t* variable = jm_vector_get_last(jm_named_ptr)(&md->variablesByName).ptr;
745 fmi1_xml_variable_type_base_t * declaredType = 0;
746 fmi1_xml_integer_type_props_t * type = 0;
749 if (context->skipOneVariableFlag) {
752 /* don't do anything. might give out a warning if(data[0] != 0) */
756 assert(!variable->typeBase);
758 declaredType = fmi1_get_declared_type(context, fmi1_xml_elmID_Enumeration,&td->defaultEnumType.typeBase);
760 if(!declaredType) return -1;
763 int hasQuan = fmi1_xml_is_attr_defined(context, fmi_attr_id_quantity);
764 int hasMin = fmi1_xml_is_attr_defined(context, fmi_attr_id_min);
765 int hasMax = fmi1_xml_is_attr_defined(context, fmi_attr_id_max);
767 if(hasQuan || hasMin || hasMax) {
768 fmi1_xml_integer_type_props_t* props = 0;
770 if(declaredType->structKind != fmi1_xml_type_struct_enu_typedef)
771 props = (fmi1_xml_integer_type_props_t*)declaredType;
773 props = (fmi1_xml_integer_type_props_t*)declaredType->baseTypeStruct;
774 assert(props->typeBase.structKind == fmi1_xml_type_struct_enu_props);
775 fmi1_xml_reserve_parse_buffer(context, 1, 0);
776 fmi1_xml_reserve_parse_buffer(context, 2, 0);
777 type = fmi1_xml_parse_integer_type_properties(context, fmi1_xml_elmID_Enumeration);
779 type->typeBase.baseTypeStruct = declaredType;
780 if(!hasMin) type->typeMin = props->typeMin;
781 if(!hasMax) type->typeMax = props->typeMax;
782 if(!hasQuan) type->quantity = props->quantity;
785 type = (fmi1_xml_integer_type_props_t*)declaredType;
788 variable->typeBase = &type->typeBase;
790 hasStart = fmi1_xml_is_attr_defined(context,fmi_attr_id_start);
792 fmi1_xml_variable_start_integer_t * start = (fmi1_xml_variable_start_integer_t*)fmi1_xml_alloc_variable_type_start(td, &type->typeBase, sizeof(fmi1_xml_variable_start_integer_t ));
795 fmi1_xml_parse_fatal(context, "Could not allocate memory");
799 /* <xs:attribute name="start" type="xs:integer"/> */
800 fmi1_xml_set_attr_int(context, fmi1_xml_elmID_Enumeration, fmi_attr_id_start, 0, &start->start, 0) ||
801 /* <xs:attribute name="fixed" type="xs:boolean"> */
802 fmi1_xml_set_attr_boolean(context, fmi1_xml_elmID_Enumeration, fmi_attr_id_fixed, 0, &isFixedBuf, 1)
805 start->typeBase.isFixed = isFixedBuf;
806 variable->typeBase = &start->typeBase;
808 fmi1_log_error_if_start_required(context, variable);
813 static int fmi1_xml_compare_variable_original_index (const void* first, const void* second) {
814 size_t a = (*(fmi1_xml_variable_t**)first)->originalIndex;
815 size_t b = (*(fmi1_xml_variable_t**)second)->originalIndex;
821 void fmi1_xml_eliminate_bad_alias(fmi1_xml_parser_context_t *context, jm_vector(jm_voidp)* varByVR, size_t indexVR) {
824 fmi1_xml_variable_t* v = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(varByVR, indexVR);
825 fmi1_value_reference_t vr = v->vr;
826 fmi1_base_type_enu_t vt = fmi1_xml_get_variable_base_type(v);
829 n = jm_vector_get_size(jm_voidp)(varByVR);
830 v = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(varByVR, indexVR);
832 jm_vector_remove_item_jm_voidp(varByVR, indexVR);
834 index = jm_vector_bsearch_index(jm_named_ptr)(&context->modelDescription->variablesByName, &key, jm_compare_named);
836 jm_vector_remove_item(jm_named_ptr)(&context->modelDescription->variablesByName, index);
838 index = jm_vector_bsearch_index(jm_voidp)(context->modelDescription->variablesOrigOrder, (jm_voidp*)&v, fmi1_xml_compare_variable_original_index);
841 jm_vector_remove_item(jm_voidp)(context->modelDescription->variablesOrigOrder,index);
843 jm_log_error(context->callbacks, module,"Removing incorrect alias variable '%s'", v->name);
844 context->callbacks->free(v);
847 static size_t fmi1_xml_eliminate_bad_alias_set(fmi1_xml_parser_context_t *context, size_t indexVR) {
\r
848 size_t i, n, removed_aliases;
\r
850 jm_vector(jm_voidp)* varByVR = context->modelDescription->variablesByVR;
\r
851 fmi1_xml_variable_t* v = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(varByVR, indexVR);
\r
852 fmi1_value_reference_t vr = v->vr;
\r
853 fmi1_base_type_enu_t vt = fmi1_xml_get_variable_base_type(v);
\r
855 jm_log_error(context->callbacks, module, "Alias set with vr=%u "
856 "(type=%s) do not have a 'noAlias' variable.", v->vr,
857 fmi1_base_type_to_string(fmi1_xml_get_variable_base_type(v)));
\r
859 removed_aliases = 0;
\r
860 n = jm_vector_get_size(jm_voidp)(varByVR);
\r
861 for(i = 0; i< n; i++) {
\r
862 v = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(varByVR, i);
\r
863 if ((v->vr == vr) && (vt == fmi1_xml_get_variable_base_type(v))) {
\r
864 fmi1_xml_eliminate_bad_alias(context, varByVR, i);
\r
865 n--; i--; removed_aliases++;
\r
869 return removed_aliases;
872 static int fmi1_xml_compare_vr_and_original_index (const void* first, const void* second) {
873 int ret = fmi1_xml_compare_vr(first, second);
875 fmi1_xml_variable_t* a = *(fmi1_xml_variable_t**)first;
876 fmi1_xml_variable_t* b = *(fmi1_xml_variable_t**)second;
877 size_t ai = a->originalIndex;
878 size_t bi = b->originalIndex;
880 if(ai < bi) ret = -1;
886 static int fmi1_same_vr_and_base_type(
887 fmi1_xml_variable_t* a,
888 fmi1_xml_variable_t* b)
890 return (a->vr == b->vr) &&
\r
891 (fmi1_xml_get_variable_base_type(a) == fmi1_xml_get_variable_base_type(b));
894 static fmi1_xml_variable_t* findNextBaseAliasIdx(
895 fmi1_xml_parser_context_t *context,
896 jm_vector(jm_voidp)* varByVR,
900 fmi1_xml_variable_t* a;
902 n = jm_vector_get_size(jm_voidp)(varByVR);
903 a = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(varByVR, cur_list_idx);
904 if (a->aliasKind == fmi1_variable_is_not_alias) {
908 for (i = cur_list_idx + 1; i < n; i++) {
909 fmi1_xml_variable_t* b =
910 (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(varByVR, i);
912 if (!fmi1_same_vr_and_base_type(a, b)) {
913 size_t aliases_removed;
915 /* End of alias set, did not find base in current so remove it */
916 aliases_removed = fmi1_xml_eliminate_bad_alias_set(context, i - 1);
918 /* Setup for iterating through the next alias set */
919 n -= aliases_removed; i -= aliases_removed;
922 if (b->aliasKind == fmi1_variable_is_not_alias) {
927 /* Did not find a next base alias */
928 fmi1_xml_eliminate_bad_alias_set(context, i - 1);
932 static int fmi1_alias_check_sign(
933 fmi1_xml_variable_t* a,
934 fmi1_xml_variable_t* b)
936 if ((a->aliasKind == fmi1_variable_is_negated_alias) !=
937 (b->aliasKind == fmi1_variable_is_negated_alias))
945 static const char* fmi1_alias_negated_string(fmi1_xml_variable_t* a) {
946 return a->aliasKind == fmi1_variable_is_negated_alias ?
947 "(negated alias)" : "";
950 #define FMIL_ABS(X) (((X) > 0) ? (X) : -(X))
951 #define FMIL_MAX(X, Y) ((X) > (Y) ? (X) : (Y))
953 static int fmi1_real_alias_consistent_start_values(
955 fmi1_xml_variable_t* a,
956 fmi1_xml_variable_t* b)
958 double a_start = fmi1_xml_get_real_variable_start(fmi1_xml_get_variable_as_real(a));
959 double b_start = fmi1_xml_get_real_variable_start(fmi1_xml_get_variable_as_real(b));
961 int check_sign = fmi1_alias_check_sign(a, b);
964 scaling = FMIL_MAX(FMIL_ABS(a_start), 1.0);
965 consistent = FMIL_ABS(a_start - check_sign*b_start) < 1e-14 * scaling;
967 jm_log_error(cb, module, "Inconsistent start values in alias set, "
968 "start value '%16.16f' of '%s'%s does not match "
969 "start value '%16.16f' of '%s'%s.",
970 a_start, a->name, fmi1_alias_negated_string(a),
971 b_start, b->name, fmi1_alias_negated_string(b));
977 static int fmi1_int_alias_consistent_start_values(
979 fmi1_xml_variable_t* a,
980 fmi1_xml_variable_t* b)
982 int a_start = fmi1_xml_get_integer_variable_start(fmi1_xml_get_variable_as_integer(a));
983 int b_start = fmi1_xml_get_integer_variable_start(fmi1_xml_get_variable_as_integer(b));
984 int check_sign = fmi1_alias_check_sign(a, b);
987 consistent = (a_start == check_sign*b_start);
989 jm_log_error(cb, module, "Inconsistent start values in alias set, "
990 "start value '%d' of '%s'%s does not match "
991 "start value '%d' of '%s'%s.",
992 a_start, a->name, fmi1_alias_negated_string(a),
993 b_start, b->name, fmi1_alias_negated_string(b));
999 static int fmi1_enum_alias_consistent_start_values(
1001 fmi1_xml_variable_t* a,
1002 fmi1_xml_variable_t* b)
1004 int a_start = fmi1_xml_get_enum_variable_start(fmi1_xml_get_variable_as_enum(a));
1005 int b_start = fmi1_xml_get_enum_variable_start(fmi1_xml_get_variable_as_enum(b));
1006 int check_sign = fmi1_alias_check_sign(a, b);
1009 consistent = (check_sign > 0) && (a_start == b_start);
1011 jm_log_error(cb, module, "Inconsistent start values in alias set, "
1012 "start value '%d' of '%s'%s does not match "
1013 "start value '%d' of '%s'%s.",
1014 a_start, a->name, fmi1_alias_negated_string(a),
1015 b_start, b->name, fmi1_alias_negated_string(b));
1021 static int fmi1_bool_alias_consistent_start_values(
1023 fmi1_xml_variable_t* a,
1024 fmi1_xml_variable_t* b)
1026 fmi1_boolean_t a_start = fmi1_xml_get_boolean_variable_start(fmi1_xml_get_variable_as_boolean(a));
1027 fmi1_boolean_t b_start = fmi1_xml_get_boolean_variable_start(fmi1_xml_get_variable_as_boolean(b));
1028 int check_sign = fmi1_alias_check_sign(a, b);
1031 if (check_sign > 0) {
1032 consistent = ((!a_start) == (!b_start));
1034 consistent = ((!a_start) != (!b_start));
1037 jm_log_error(cb, module, "Inconsistent start values in alias set, "
1038 "start value '%s' of '%s'%s does not match "
1039 "start value '%s' of '%s'%s.",
1040 a_start ? "true" : "false", a->name, fmi1_alias_negated_string(a),
1041 b_start ? "true" : "false", b->name, fmi1_alias_negated_string(b));
1047 static int fmi1_str_alias_consistent_start_values(
1049 fmi1_xml_variable_t* a,
1050 fmi1_xml_variable_t* b)
1052 const char* a_start = fmi1_xml_get_string_variable_start(fmi1_xml_get_variable_as_string(a));
1053 const char* b_start = fmi1_xml_get_string_variable_start(fmi1_xml_get_variable_as_string(b));
1054 int check_sign = fmi1_alias_check_sign(a, b);
1057 consistent = check_sign > 0 && strcmp(a_start, b_start) == 0;
1059 jm_log_error(cb, module, "Inconsistent start values in alias set, "
1060 "start value '%s' of '%s'%s does not match "
1061 "start value '%s' of '%s'%s.",
1062 a_start, a->name, fmi1_alias_negated_string(a),
1063 b_start, b->name, fmi1_alias_negated_string(b));
1069 static int fmi1_alias_consistent_start_values(
1071 fmi1_xml_variable_t* a,
1072 fmi1_xml_variable_t* b)
1074 fmi1_base_type_enu_t type = fmi1_xml_get_variable_base_type(a);
1075 assert(fmi1_same_vr_and_base_type(a, b));
1078 case fmi1_base_type_real:
1079 return fmi1_real_alias_consistent_start_values(cb, a, b);
1080 case fmi1_base_type_int:
1081 return fmi1_int_alias_consistent_start_values(cb, a, b);
1082 case fmi1_base_type_bool:
1083 return fmi1_bool_alias_consistent_start_values(cb, a, b);
1084 case fmi1_base_type_str:
1085 return fmi1_str_alias_consistent_start_values(cb, a, b);
1086 case fmi1_base_type_enum:
1087 return fmi1_enum_alias_consistent_start_values(cb, a, b);
1088 default: assert(0); return 0;
1092 static size_t handleAliasSet(
1093 fmi1_xml_parser_context_t *context,
1094 jm_vector(jm_voidp)* varByVR,
1095 fmi1_xml_variable_t* base_alias,
1098 size_t numvar, cur_list_idx;
1099 fmi1_xml_variable_t* v_with_start = NULL;
1101 numvar = jm_vector_get_size(jm_voidp)(varByVR);
1102 if (numvar <= start_idx) {
1103 /* Nothing to do if past the end of the list */
1104 return start_idx + 1;
1107 assert(base_alias->aliasKind == fmi1_variable_is_not_alias);
1108 if (fmi1_xml_get_variable_has_start(base_alias)) {
1109 /* If base alias have start, use it as the correct value
1110 * when comparing against other vars so we don'r remove
1111 * it from the alias set */
1112 v_with_start = base_alias;
1114 for(cur_list_idx = start_idx; cur_list_idx < numvar; cur_list_idx++) {
1115 fmi1_xml_variable_t* v = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(varByVR, cur_list_idx);
1117 if (v == base_alias) {
1118 /* The base alias, nothing to do */
1121 if (!fmi1_same_vr_and_base_type(base_alias, v)) {
1122 /* Not the same vr and type, end of the alias set */
1125 /* Next variable in list have same type and valueRef */
1126 if (v->aliasKind == fmi1_variable_is_not_alias) {
1127 /* But is for some reason marked as 'noAlias' => make it an alias */
1128 fmi1_xml_variable_t* c;
1131 jm_log_error(context->callbacks, module, "Variables %s and %s reference the "
1132 "same vr %u. Marking '%s' as alias.",
1133 base_alias->name, v->name, v->vr, v->name);
1134 v->aliasKind = fmi1_variable_is_alias;
1136 /* Ok, now we sort b into a later position in the var list
1137 * which is consistent with the lists sorting */
1139 j = cur_list_idx + 1;
1141 c = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(varByVR, j);
1142 if(fmi1_xml_compare_vr(&v,&c) <= 0) break;
1147 c = (fmi1_xml_variable_t*)jm_vector_get_item(jm_voidp)(varByVR, j);
1148 jm_vector_set_item(jm_voidp)(varByVR, j, v);
1149 jm_vector_set_item(jm_voidp)(varByVR, i, c);
1152 /* Now that this inconsistency is taken care of we repeat
1153 * current loop iteration: */
1156 } else if (fmi1_xml_get_variable_has_start(v)) {
1157 if (v_with_start == NULL) {
1159 } else if (!fmi1_alias_consistent_start_values(
1160 context->callbacks, v_with_start, v))
1162 fmi1_xml_eliminate_bad_alias(context, varByVR, cur_list_idx);
1163 cur_list_idx--; numvar--;
1169 return cur_list_idx;
1172 static void fmi1_checking_alias_info(
1173 fmi1_xml_parser_context_t *context,
1174 jm_vector(jm_voidp)* varByVR)
1176 size_t cur_list_idx = 0;
1178 jm_log_verbose(context->callbacks, module,"Checking alias information");
1179 while (cur_list_idx < jm_vector_get_size(jm_voidp)(varByVR)) {
1180 fmi1_xml_variable_t* base_alias = findNextBaseAliasIdx(context, varByVR, cur_list_idx);
1181 if (base_alias == NULL) break;
1182 cur_list_idx = handleAliasSet(context, varByVR, base_alias, cur_list_idx);
1186 int fmi1_xml_handle_ModelVariables(fmi1_xml_parser_context_t *context, const char* data) {
1188 jm_log_verbose(context->callbacks, module,"Parsing XML element ModelVariables");
1191 /* postprocess variable list */
1193 fmi1_xml_model_description_t* md = context->modelDescription;
1194 jm_vector(jm_voidp)* varByVR;
1195 jm_vector(jm_voidp)* inputVars;
1196 jm_vector(jm_voidp)* outputVars;
1200 numvar = jm_vector_get_size(jm_named_ptr)(&md->variablesByName);
1201 inputVars = jm_vector_alloc(jm_voidp)(numvar,numvar,md->callbacks);
1202 outputVars = jm_vector_alloc(jm_voidp)(numvar,numvar,md->callbacks);
1203 if (!inputVars || !outputVars) {
1204 fmi1_xml_parse_fatal(context, "Could not allocate memory");
1206 /* vars with vr = fmiUndefinedValueReference were already skipped. Just sanity: */
1207 /* remove any variable with vr = fmiUndefinedValueReference */
1208 for(i = 0; i< numvar; i++) {
1209 jm_named_ptr named = jm_vector_get_item(jm_named_ptr)(&md->variablesByName, i);
1210 fmi1_xml_variable_t* v = named.ptr;
1211 if(v->vr == fmi1_undefined_value_reference) {
1212 jm_vector_remove_item(jm_named_ptr)(&md->variablesByName,i);
1214 fmi1_xml_free_direct_dependencies(named);
1215 md->callbacks->free(v);
1218 if (v->causality == fmi1_causality_enu_input){
1219 jm_vector_set_item(jm_voidp)(inputVars, num_in, jm_vector_get_item(jm_named_ptr)(&md->variablesByName,i).ptr);
1222 if (v->causality == fmi1_causality_enu_output){
1223 jm_vector_set_item(jm_voidp)(outputVars, num_out, jm_vector_get_item(jm_named_ptr)(&md->variablesByName,i).ptr);
1229 /* store the list of vars in origianl order */
1231 size_t size = jm_vector_get_size(jm_named_ptr)(&md->variablesByName);
1232 md->variablesOrigOrder = jm_vector_alloc(jm_voidp)(size,size,md->callbacks);
1233 if(md->variablesOrigOrder) {
1235 for(i= 0; i < size; ++i) {
1236 jm_vector_set_item(jm_voidp)(md->variablesOrigOrder, i, jm_vector_get_item(jm_named_ptr)(&md->variablesByName,i).ptr);
1242 /* store the list of input vars */
1243 md->inputVariables = jm_vector_alloc(jm_voidp)(num_in,num_in,md->callbacks);
1244 md->outputVariables = jm_vector_alloc(jm_voidp)(num_out,num_out,md->callbacks);
1245 if(md->inputVariables) {
1247 for(i= 0; i < num_in; ++i) {
1248 jm_vector_set_item(jm_voidp)(md->inputVariables, i, jm_vector_get_item(jm_voidp)(inputVars,i));
1252 fmi1_xml_parse_fatal(context, "Could not allocate memory");
1254 if(md->outputVariables) {
1256 for(i= 0; i < num_out; ++i) {
1257 jm_vector_set_item(jm_voidp)(md->outputVariables, i, jm_vector_get_item(jm_voidp)(outputVars,i));
1261 fmi1_xml_parse_fatal(context, "Could not allocate memory");
1263 jm_vector_free(jm_voidp)(inputVars);
1264 jm_vector_free(jm_voidp)(outputVars);
1266 /* sort the variables by names */
1267 jm_vector_qsort(jm_named_ptr)(&md->variablesByName,jm_compare_named);
1269 /* create VR index */
1270 md->status = fmi1_xml_model_description_enu_ok;
1272 size_t size = jm_vector_get_size(jm_named_ptr)(&md->variablesByName);
1273 md->variablesByVR = jm_vector_alloc(jm_voidp)(size,size,md->callbacks);
1274 if(md->variablesByVR) {
1276 for(i= 0; i < size; ++i) {
1277 jm_vector_set_item(jm_voidp)(md->variablesByVR, i, jm_vector_get_item(jm_named_ptr)(&md->variablesByName,i).ptr);
1283 md->status = fmi1_xml_model_description_enu_empty;
1284 if(!md->variablesByVR || !md->variablesOrigOrder || !md->inputVariables || !md->outputVariables) {
1285 fmi1_xml_parse_fatal(context, "Could not allocate memory");
1288 varByVR = md->variablesByVR;
1289 jm_vector_qsort(jm_voidp)(varByVR, fmi1_xml_compare_vr_and_original_index);
1291 fmi1_checking_alias_info(context, varByVR);
1293 numvar = jm_vector_get_size(jm_named_ptr)(&md->variablesByName);
1294 jm_log_verbose(context->callbacks, module,"Setting up direct dependencies cross-references");
1295 /* postprocess direct dependencies */
1296 for(i = 0; i< numvar; i++) {
1297 size_t numdep, j, var_i = 0;
1298 jm_vector(jm_voidp)* dep;
1299 fmi1_xml_variable_t* variable = (fmi1_xml_variable_t*)jm_vector_get_item(jm_named_ptr)(&md->variablesByName, i).ptr;
1301 if(!variable->directDependency) continue;
1302 dep = variable->directDependency;
1303 numdep = jm_vector_get_size(jm_voidp)(dep);
1304 for(j = 0; j < numdep; j++) {
1305 jm_string name = jm_vector_get_item(jm_voidp)(dep, j);
1306 jm_named_ptr key, *found;
1307 fmi1_xml_variable_t* depvar;
1310 found = jm_vector_bsearch(jm_named_ptr)(&md->variablesByName, &key, jm_compare_named);
1312 depvar = found->ptr;
1316 jm_log_error(context->callbacks,module, "Could not find variable %s mentioned in dependecies of %s. Ignoring", name, variable->name);
1319 if(depvar->causality != fmi1_causality_enu_input) {
1320 jm_log_error(context->callbacks,module, "Only input variables are allowed in DirectDependecies, but %s is not input. Ignoring", name);
1323 jm_vector_set_item(jm_voidp)(dep,var_i++, depvar);
1325 jm_vector_resize(jm_voidp)(dep,var_i);
1327 jm_vector_foreach(jm_string)(&context->directDependencyStringsStore, (void(*)(jm_string))context->callbacks->free);
1328 jm_vector_free_data(jm_string)(&context->directDependencyStringsStore);
1330 /* might give out a warning if(data[0] != 0) */