// Pop the children from the stack and // check for correct type and sequence of children static void XMLCALL endElement(void *context, const char *elm) { Elm el; el = checkElement(elm); assert((el >= elm_fmiModelDescription) && (el <=elm_Enumeration)); switch(el) { case elm_fmiModelDescription: { ModelDescription* md; ListElement** ud = NULL; // NULL or list of BaseUnits Type** td = NULL; // NULL or list of Types Element* de = NULL; // NULL or DefaultExperiment ListElement** va = NULL; // NULL or list of Tools ScalarVariable** mv = NULL; // NULL or list of ScalarVariable ListElement* child; child = checkPop(ANY_TYPE); if (child->type == elm_ModelVariables){ mv = (ScalarVariable**)child->list; free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_VendorAnnotations){ va = (ListElement**)child->list; free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_DefaultExperiment){ de = (Element*)child; child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_TypeDefinitions){ td = (Type**)child->list; free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_UnitDefinitions){ ud = (ListElement**)child->list; free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (!checkElementType(child, elm_fmiModelDescription)) return; md = (ModelDescription*)child; md->modelVariables = mv; md->vendorAnnotations = va; md->defaultExperiment = de; md->typeDefinitions = td; md->unitDefinitions = ud; stackPush(stack, md); break; } case elm_Type: { Type* tp; Element* ts = checkPop(ANY_TYPE); if (!ts) return; if (!checkPeek(elm_Type)) return; tp = (Type*)stackPeek(stack); switch (ts->type) { case elm_RealType: case elm_IntegerType: case elm_BooleanType: case elm_EnumerationType: break; default: logFatalTypeError("RealType or similar", ts->type); return; } tp->typeSpec = ts; break; } case elm_ScalarVariable: { ScalarVariable* sv; Element** list = NULL; Element* child = checkPop(ANY_TYPE); if (!child) return; if (child->type==elm_DirectDependency){ list = ((ListElement*)child)->list; free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (!checkPeek(elm_ScalarVariable)) return; sv = (ScalarVariable*)stackPeek(stack); switch (child->type) { case elm_Real: case elm_Integer: case elm_Boolean: case elm_Enumeration: break; default: logFatalTypeError("Real or similar", child->type); return; } sv->directDependencies = list; sv->typeSpec = child; break; } case elm_ModelVariables: popList(elm_ScalarVariable); break; case elm_VendorAnnotations: popList(elm_Tool);break; case elm_Tool: popList(elm_Annotation); break; case elm_TypeDefinitions: popList(elm_Type); break; case elm_EnumerationType: popList(elm_Item); break; case elm_UnitDefinitions: popList(elm_BaseUnit); break; case elm_BaseUnit: popList(elm_DisplayUnitDefinition); break; case elm_DirectDependency: popList(elm_Name); break; case elm_Name: { // Exception: the name value is represented as element content. // All other values of the XML file are represented using attributes. Element* name = checkPop(elm_Name); if (!name) return; name->n = 2; name->attributes = malloc(2*sizeof(char*)); name->attributes[0] = attNames[att_input]; name->attributes[1] = data; data = NULL; skipData = 1; // stop recording element content stackPush(stack, name); break; } default: // must be a leaf Element assert(getAstNodeType(el)==astElement); break; } // All children of el removed from the stack. // The top element must be of type el now. checkPeek(el); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// Pop the children from the stack and check for correct type and sequence of children /// This is the end handler of parser. The parser ends here. /// ///\param context ///\param elm ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// static void XMLCALL endElement(void *context, const char *elm) { Elm el; el = checkElement(elm); printfDebug(" **** ending element %s.\n", elmNames[el]); switch(el) { case elm_fmiModelDescription: { ModelDescription* md; ListElement** im = NULL; // NULL or list of CoSimulation_StandAlone under Implementation ListElement** ud = NULL; // NULL or list of BaseUnits under UnitDefinitions Type** td = NULL; // NULL or list of Types under TypeDefinitions Element* de = NULL; // NULL or DefaultExperiment ListElement** va = NULL; // NULL or list of Tools ScalarVariable** mv = NULL; // NULL or list of ScalarVariables under ModelVariables ListElement* child; printDebug("$$$$$ entered endElement 'elm_fmiModelDescription'\n"); child = checkPop(ANY_TYPE); // get a child from stack while (child && child->type != elm_fmiModelDescription) // add while-loop in case the elements in the random order { if (child->type == elm_VendorAnnotations){ va = (ListElement**)child->list; // VendorAnnotations (ListElement) contains Tool (ListElement)) free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_DefaultExperiment){ de = (Element*)child; // DefaultExperiment (Element) with only attributes child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_TypeDefinitions){ td = (Type**)child->list; // TypeDefinitions (ListElement) contains Type (Type) free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_UnitDefinitions){ ud = (ListElement**)child->list; // UnitDefinitions (ListElement) contains BaseUnit (ListElement) free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (child->type == elm_Implementation){ // Implementation is listElement, it can be treated the same as UnitDefinitions im = (ListElement**)child->list; // Implementation (Implementation) contains CoSimulation_StandAlone (ListElement) free(child); // Zuo: child = checkPop(ANY_TYPE); // Zuo: if (!child) return; // Zuo: } // Zuo: if (child->type == elm_ModelVariables){ mv = (ScalarVariable**)child->list; // ModelVariables (ListElement) contains ScalarVariable (ScalarVariable) free(child); child = checkPop(ANY_TYPE); if (!child) return; } } printDebug("$$$$$ checking element type \n"); if (checkElementType(child, elm_fmiModelDescription)) return; printDebug("$$$$$ checked element type \n"); md = (ModelDescription*)child; // the following build the link of elements for ModelDescriptions md->modelVariables = mv; md->implementation = im; // added M. Wetter md->vendorAnnotations = va; md->defaultExperiment = de; md->typeDefinitions = td; md->unitDefinitions = ud; printDebug("$$$$$ calling stackPush \n"); stackPush(stack, md); printDebug("$$$$$ called stackPush \n"); break; } case elm_Type: { Type* tp; Element* ts = checkPop(ANY_TYPE); if (!ts) return; // If there is no sub-element, return if (checkPeek(elm_Type)) return; // If the sub-element is not Type, return tp = (Type*)stackPeek(stack); // Get the element switch (ts->type) { case elm_RealType: case elm_IntegerType: case elm_BooleanType: case elm_EnumerationType: case elm_StringType: break; default: // Element type does not match logFatalTypeError("RealType or similar", ts->type); return; } tp->typeSpec = ts; // parent (tp) links to sub-element (ts) break; } case elm_ScalarVariable: { ScalarVariable* sv; Element** list = NULL; Element* child = checkPop(ANY_TYPE); if (!child) return; if (child->type==elm_DirectDependency){ list = ((ListElement*)child)->list; // DirectDependency is ListElement free(child); child = checkPop(ANY_TYPE); if (!child) return; } if (checkPeek(elm_ScalarVariable)) return; // If next element is not ScalarVariable, return sv = (ScalarVariable*)stackPeek(stack); switch (child->type) { case elm_Real: case elm_Integer: case elm_Boolean: case elm_Enumeration: case elm_String: break; default: logFatalTypeError("Real or similar", child->type); return; } sv->directDependencies = list; sv->typeSpec = child; break; } case elm_Implementation: popList(elm_CoSimulation_StandAlone); break; // Needs to be modified if CoSimulation_Tool is added case elm_CoSimulation_StandAlone: popList(elm_Capabilities); break; // CoSimulation_StandAlone only has Capabilities case elm_ModelVariables: popList(elm_ScalarVariable); break; case elm_VendorAnnotations: popList(elm_Tool);break; case elm_Tool: popList(elm_Annotation); break; case elm_TypeDefinitions: popList(elm_Type); break; case elm_EnumerationType: popList(elm_Item); break; case elm_UnitDefinitions: popList(elm_BaseUnit); break; case elm_BaseUnit: popList(elm_DisplayUnitDefinition); break; case elm_DirectDependency: popList(elm_Name); break; case elm_Name: { // Exception: the name value is represented as element content. // All other values of the XML file are represented using attributes. Element* name = checkPop(elm_Name); if (!name) return; name->n = 2; name->attributes = malloc(2*sizeof(char*)); name->attributes[0] = attNames[att_input]; name->attributes[1] = data; data = NULL; skipData = 1; // stop recording element content stackPush(stack, name); break; } case -1: return; // illegal element error default: // must be a leaf Element printDebug("+++++++ got a leaf element\n"); assert(getAstNodeType(el)==astElement); break; } // All children of el removed from the stack. // The top element must be of type el now. checkPeek(el); }