#include #include #include #include #include #include #include "rtsc.h" #include "parser.h" #include "error.h" static unsigned int event_counter = 0; char* get_value(xmlNode *node) { xmlNode *cur_node = NULL; if(node == NULL || node->children == NULL) return NULL; cur_node = node->children; while(cur_node->name != NULL && strcmp((char *)cur_node->name, RTSC_TAG_Value)) cur_node = cur_node->next; if(cur_node->children == NULL) return NULL; return (char *)cur_node->children->content; } Event* parse_event(xmlNode *node) { xmlNode *cur_node = NULL; char *content = NULL; char *type = NULL; Event *event = (Event *)malloc(sizeof(Event)); event->name = NULL; event->transition_id = NULL; for(cur_node = node; cur_node; cur_node = cur_node->next) { if(cur_node->name != NULL && cur_node->properties != NULL && cur_node->properties->name != NULL && cur_node->properties->children != NULL && cur_node->properties->children->content != NULL && !strcmp((char *)cur_node->name, RTSC_TAG_Attribute) && !strcmp((char *)cur_node->properties->name, RTSC_PROPERTY_Name)) { content = (char *)cur_node->properties->children->content; if(!strcmp(content, RTSC_NAME_EventName)) { event->name = get_value(cur_node); // no name means no event if(!strcmp(event->name, "")) { free(event); return NULL; } } else if(!strcmp(content, RTSC_NAME_EventTransReceive)) { event->transition_id = get_value(cur_node); event->type = RECEIVE; } else if(!strcmp(content, RTSC_NAME_EventTransSend)) { event->transition_id = get_value(cur_node); event->type = SEND; } } } assert(event->name && event->transition_id); // debug /*printf("event name: %s\n", event->name); printf("transition id: %s\n", event->transition_id); printf("event type: %d\n", event->type); printf("\n\n");*/ return event; } Action* parse_action(xmlNode *node) { xmlNode *cur_node = NULL; char *content = NULL; char *type = NULL; Action *action = (Action *)malloc(sizeof(Action)); action->id = NULL; // default values // TODO action->wcet = -1; action->lower = -1; action->upper = -1; for(cur_node = node; cur_node; cur_node = cur_node->next) { if(cur_node->name != NULL && cur_node->properties != NULL && cur_node->properties->name != NULL && cur_node->properties->children != NULL && cur_node->properties->children->content != NULL && !strcmp((char *)cur_node->name, RTSC_TAG_Attribute) && !strcmp((char *)cur_node->properties->name, RTSC_PROPERTY_Name)) { content = (char *)cur_node->properties->children->content; if(!strcmp(content, RTSC_NAME_ActionType)) { type = get_value(cur_node); if(!strcmp(type, RTSC_VALUE_Do)) action->type = DO; else if(!strcmp(type, RTSC_VALUE_Entry)) action->type = ENTRY; else if(!strcmp(type, RTSC_VALUE_Exit)) action->type = EXIT; else error("Failed to parse ActionType", __FILE__, __LINE__); } else if(!strcmp(content, RTSC_NAME_PeriodLowerBound)) { action->lower = atoi(get_value(cur_node)); if(action->lower == 0 && strcmp(get_value(cur_node), "0")) error("Failed to parse lower bound", __FILE__, __LINE__); } else if(!strcmp(content, RTSC_NAME_PeriodUpperBound)) { action->upper = atoi(get_value(cur_node)); if(action->upper == 0 && strcmp(get_value(cur_node), "0")) error("Failed to parse upper bound", __FILE__, __LINE__); } else if(!strcmp(content, RTSC_NAME_ActionWcet)) { action->wcet = atoi(get_value(cur_node)); if(action->wcet == 0 && strcmp(get_value(cur_node), "0")) error("Failed to parse wcet", __FILE__, __LINE__); } } } // debug /*printf("action wcet: %d\n", action->wcet); printf("action lower: %d\n", action->lower); printf("action upper: %d\n", action->upper); printf("action type: %d\n", action->type); printf("\n\n"); */ return action; } State* parse_state(xmlNode *node, StateType type) { typedef State RTS; xmlNode *cur_node = NULL; char *content = NULL; RTS *state = (RTS *)malloc(sizeof(RTS)); state->name = NULL; state->statechart = NULL; state->statechart_id = NULL; state->do_action = NULL; state->do_action_id = NULL; state->entry_action = NULL; state->entry_action_id = NULL; state->exit_action = NULL; state->exit_action_id = NULL; state->transition_list = NULL; state->type = type; GList **tl = &state->transition_list; for(cur_node = node; cur_node; cur_node = cur_node->next) { if(cur_node->name != NULL && cur_node->properties != NULL && cur_node->properties->name != NULL && cur_node->properties->children != NULL && cur_node->properties->children->content != NULL && !strcmp((char *)cur_node->name, RTSC_TAG_Attribute) && !strcmp((char *)cur_node->properties->name, RTSC_PROPERTY_Name)) { content = (char *)cur_node->properties->children->content; if(!strcmp(content, RTSC_NAME_Statechart)) state->statechart_id = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_Name)) state->name = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_DoAction)) state->do_action_id = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_EntryAction)) state->entry_action_id = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_ExitAction)) state->exit_action_id = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_TransitionIn)) *tl = g_list_prepend(*tl, get_value(cur_node)); else if(!strcmp(content, RTSC_NAME_TransitionOut)) *tl = g_list_prepend(*tl, get_value(cur_node)); } } assert(state->name && state->statechart_id); // debug /*printf("state name: %s\n", state->name); printf("statechart id: %s\n", state->statechart_id); printf("state type: %d\n", state->type); if(state->do_action_id) printf("do action id: %s\n", state->do_action_id); if(state->entry_action_id) printf("entry action id: %s\n", state->entry_action_id); if(state->exit_action_id) printf("exit action id: %s\n", state->exit_action_id); while(state->transition_list) { printf("transition list: %s\n", (char *)state->transition_list->data); state->transition_list = state->transition_list->next; } printf("\n\n");**/ return state; } Statechart* parse_statechart(xmlNode *node) { typedef Statechart RTSC; xmlNode *cur_node = NULL; char *content = NULL; RTSC *state = (RTSC *)malloc(sizeof(RTSC)); state->name = NULL; state->state_list = NULL; state->transition_list = NULL; GList **sl = &state->state_list; GList **tl = &state->transition_list; for(cur_node = node; cur_node; cur_node = cur_node->next) { if(cur_node->name != NULL && cur_node->properties != NULL && cur_node->properties->name != NULL && cur_node->properties->children != NULL && cur_node->properties->children->content != NULL && !strcmp((char *)cur_node->name, RTSC_TAG_Attribute) && !strcmp((char *)cur_node->properties->name, RTSC_PROPERTY_Name)) { content = (char *)cur_node->properties->children->content; if(!strcmp(content, RTSC_NAME_IsTopStatechart)) state->is_top_statechart = !strcmp(get_value(cur_node), RTSC_VALUE_True); else if(!strcmp(content, RTSC_NAME_Name)) state->name = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_State)) *sl = g_list_prepend(*sl, get_value(cur_node)); else if(!strcmp(content, RTSC_NAME_Transition)) *tl = g_list_prepend(*tl, get_value(cur_node)); } } // debug /*printf("%d\n", state->is_top_statechart); if(state->name != NULL) printf("%s\n", state->name); while(state->transition_list) { printf("%s ", (char *)state->transition_list->data); state->transition_list = state->transition_list->next; } printf("\n"); while(state->state_list) { printf("%s ", (char *)state->state_list->data); state->state_list = state->state_list->next; } printf("\n\n");*/ return state; } Transition* parse_transition(xmlNode *node) { typedef Transition RTT; xmlNode *cur_node = NULL; char *content = NULL; RTT *trans = (RTT *)malloc(sizeof(RTT)); trans->name = NULL; trans->statechart = NULL; trans->from = NULL; trans->to = NULL; trans->event_send = NULL; trans->event_receive = NULL; trans->statechart_id = NULL; trans->from_id = NULL; trans->to_id = NULL; trans->event_send_id = NULL; trans->event_receive_id = NULL; for(cur_node = node; cur_node; cur_node = cur_node->next) { if(cur_node->name != NULL && cur_node->properties != NULL && cur_node->properties->name != NULL && cur_node->properties->children != NULL && cur_node->properties->children->content != NULL && !strcmp((char *)cur_node->name, RTSC_TAG_Attribute) && !strcmp((char *)cur_node->properties->name, RTSC_PROPERTY_Name)) { content = (char *)cur_node->properties->children->content; if(!strcmp(content, RTSC_NAME_NameTrans)) trans->name = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_StatechartTrans)) trans->statechart_id = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_StateFrom)) trans->from_id = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_StateTo)) trans->to_id = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_EventSend)) trans->event_send_id = get_value(cur_node); else if(!strcmp(content, RTSC_NAME_EventReceive)) trans->event_receive_id = get_value(cur_node); } } assert(trans->name && trans->statechart_id && trans->from_id && trans->to_id); // debug /*printf("transition name: %s\n", trans->name); printf("statechart id: %s\n", (char *)trans->statechart_id); printf("from id: %s\n", (char *)trans->from_id); printf("to id: %s\n", (char *)trans->to_id); if(trans->event_send_id) printf("event send id: %s\n", (char *)trans->event_send_id); if(trans->event_receive_id) printf("event receive id: %s\n", (char *)trans->event_receive_id); printf("\n\n");*/ return trans; } int parse_tree(xmlNode *node, GHashTable *ht, GHashTable *event_ht, GList **sc_list_ptr) { xmlNode *cur_node = NULL; char *content = NULL; char *id = NULL; xmlNode *par = NULL; void *state = NULL; Object *obj = NULL; ObjectType type; for(cur_node = node; cur_node; cur_node = cur_node->next) { par = cur_node->parent; if(cur_node->type == XML_ELEMENT_NODE && cur_node->name != NULL && cur_node->children != NULL && cur_node->children->content != NULL && par != NULL && par->properties != NULL && par->properties->children != NULL && par->properties->name != NULL && !strcmp((char *)cur_node->name, RTSC_TAG_Class) && !strcmp((char *)par->properties->name, RTSC_PROPERTY_Id)) { content = (char *)cur_node->children->content; id = (char *)par->properties->children->content; if(!strcmp(content, RTSC_CLASS_Statechart)) { state = parse_statechart(cur_node); ((Statechart *)state)->id = id; type = STATECHART; *sc_list_ptr = g_list_prepend(*sc_list_ptr, state); } else if(!strcmp(content, RTSC_CLASS_StartState)) { state = parse_state(cur_node, START); ((State *)state)->id = id; type = STATE; } else if(!strcmp(content, RTSC_CLASS_StopState)) { state = parse_state(cur_node, STOP); ((State *)state)->id = id; type = STATE; } else if(!strcmp(content, RTSC_CLASS_State)) { state = parse_state(cur_node, NORMAL); ((State *)state)->id = id; type = STATE; } else if(!strcmp(content, RTSC_CLASS_Transition)) { state = parse_transition(cur_node); ((Transition *)state)->id = id; type = TRANSITION; } else if(!strcmp(content, RTSC_CLASS_Action)) { state = parse_action(cur_node); ((Transition *)state)->id = id; type = ACTION; } else if(!strcmp(content, RTSC_CLASS_Event)) { Event *event; int *num; state = parse_event(cur_node); event = (Event *)state; num = g_hash_table_lookup(event_ht, event->name); if(num) event->number = *num; else { event->number = event_counter++; g_hash_table_insert(event_ht, event->name, &event->number); } event->id = id; type = EVENT; } if(state != NULL) { obj = (Object *)malloc(sizeof(Object)); obj->type = type; obj->obj = state; g_hash_table_insert(ht, id, obj); } } parse_tree(cur_node->children, ht, event_ht, sc_list_ptr); } return event_counter; }