All pastes #445341 Raw Edit

Anonymous

public text v1 · immutable
·published 2007-04-17 20:27 UTC
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;
}