rendered paste body#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <glib.h>
#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;
}