add Cyberiada Document structure to allow multi-sm files

This commit is contained in:
Alexey Fedoseev
2024-03-31 17:50:49 +03:00
parent 235e91437a
commit 2dcb773997
3 changed files with 258 additions and 171 deletions

View File

@@ -243,7 +243,7 @@ static CyberiadaNode* cyberiada_new_node(const char* id)
new_node->type = cybNodeSimpleState;
new_node->title = NULL;
new_node->title_len = 0;
new_node->action = NULL;
new_node->actions = NULL;
new_node->next = NULL;
new_node->parent = NULL;
new_node->children = NULL;
@@ -277,7 +277,7 @@ static int cyberiada_destroy_node(CyberiadaNode* node)
if(node->children) {
cyberiada_destroy_all_nodes(node->children);
}
if(node->action) cyberiada_destroy_action(node->action);
if(node->actions) cyberiada_destroy_action(node->actions);
if(node->geometry_rect) free(node->geometry_rect);
free(node);
}
@@ -554,7 +554,7 @@ static int cyberiada_decode_state_block_action(const char* text, CyberiadaAction
return CYBERIADA_NO_ERROR;
}
static int cyberiada_decode_state_action(const char* text, CyberiadaAction** action)
static int cyberiada_decode_state_actions(const char* text, CyberiadaAction** action)
{
int res;
size_t buffer_len;
@@ -769,9 +769,12 @@ static int cyberiada_destroy_edge(CyberiadaEdge* e)
return CYBERIADA_NO_ERROR;
}
static int cyberiada_graph_reconstruct_edges(CyberiadaSM* sm)
static int cyberiada_graphs_reconstruct_edges(CyberiadaDocument* doc)
{
CyberiadaEdge* edge = sm->edges;
CyberiadaEdge* edge;
CyberiadaSM* sm;
for (sm = doc->state_machines; sm; sm = sm->next) {
edge = sm->edges;
while (edge) {
CyberiadaNode* source = cyberiada_graph_find_node_by_id(sm->nodes, edge->source_id);
CyberiadaNode* target = cyberiada_graph_find_node_by_id(sm->nodes, edge->target_id);
@@ -783,6 +786,7 @@ static int cyberiada_graph_reconstruct_edges(CyberiadaSM* sm)
edge->target = target;
edge = edge->next;
}
}
return CYBERIADA_NO_ERROR;
}
@@ -876,11 +880,11 @@ static MetainfoDeclaration cyberiada_metadata[] = {
}
};
static int cyberiada_add_default_meta(CyberiadaSM* sm, const char* sm_name)
static int cyberiada_add_default_meta(CyberiadaDocument* doc, const char* sm_name)
{
CyberiadaMetainformation* meta;
if (sm->meta_info) {
if (doc->meta_info) {
return CYBERIADA_BAD_PARAMETER;
}
@@ -897,7 +901,7 @@ static int cyberiada_add_default_meta(CyberiadaSM* sm, const char* sm_name)
meta->actions_order_flag = 1;
meta->event_propagation_flag = 1;
sm->meta_info = meta;
doc->meta_info = meta;
return CYBERIADA_NO_ERROR;
}
@@ -1008,34 +1012,44 @@ static int cyberiada_add_default_meta(CyberiadaSM* sm, const char* sm_name)
* The Cyberiada GraphML library fucntions declarations
* ----------------------------------------------------------------------------- */
CyberiadaSM* cyberiada_create_sm(void)
static int cyberiada_init_sm(CyberiadaSM* sm)
{
if (sm) {
sm->nodes = NULL;
sm->edges = NULL;
sm->next = NULL;
}
return CYBERIADA_NO_ERROR;
}
static CyberiadaSM* cyberiada_create_sm(void)
{
CyberiadaSM* sm = (CyberiadaSM*)malloc(sizeof(CyberiadaSM));
cyberiada_init_sm(sm);
return sm;
}
int cyberiada_init_sm(CyberiadaSM* sm)
CyberiadaDocument* cyberiada_create_sm_document(void)
{
if (sm) {
sm->format = NULL;
sm->meta_info = NULL;
sm->nodes = NULL;
sm->edges = NULL;
CyberiadaDocument* doc = (CyberiadaDocument*)malloc(sizeof(CyberiadaDocument));
cyberiada_init_sm_document(doc);
return doc;
}
int cyberiada_init_sm_document(CyberiadaDocument* doc)
{
if (doc) {
doc->format = NULL;
doc->meta_info = NULL;
doc->state_machines = NULL;
}
return CYBERIADA_NO_ERROR;
}
int cyberiada_cleanup_sm(CyberiadaSM* sm)
static int cyberiada_destroy_sm(CyberiadaSM* sm)
{
CyberiadaEdge *edge, *e;
if (sm) {
if (sm->format) {
free(sm->format);
}
if (sm->meta_info) {
cyberiada_destroy_meta(sm->meta_info);
}
if (sm->nodes) {
cyberiada_destroy_all_nodes(sm->nodes);
}
@@ -1047,18 +1061,41 @@ int cyberiada_cleanup_sm(CyberiadaSM* sm)
cyberiada_destroy_edge(e);
} while (edge);
}
cyberiada_init_sm(sm);
free(sm);
}
return CYBERIADA_NO_ERROR;
}
int cyberiada_destroy_sm(CyberiadaSM* sm)
int cyberiada_cleanup_sm_document(CyberiadaDocument* doc)
{
int res = cyberiada_cleanup_sm(sm);
CyberiadaSM *sm, *sm2;
if (doc) {
if (doc->format) {
free(doc->format);
}
if (doc->meta_info) {
cyberiada_destroy_meta(doc->meta_info);
}
if (doc->state_machines) {
sm = doc->state_machines;
do {
sm2 = sm;
sm = sm->next;
cyberiada_destroy_sm(sm2);
} while (sm);
}
cyberiada_init_sm_document(doc);
}
return CYBERIADA_NO_ERROR;
}
int cyberiada_destroy_sm_document(CyberiadaDocument* doc)
{
int res = cyberiada_cleanup_sm_document(doc);
if (res != CYBERIADA_NO_ERROR) {
return res;
}
free(sm);
free(doc);
return CYBERIADA_NO_ERROR;
}
@@ -1206,11 +1243,12 @@ static int cyberiada_get_element_text(char* buffer, size_t buffer_len,
}
static GraphProcessorState handle_new_graph(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
size_t buffer_len = sizeof(buffer) - 1;
CyberiadaSM* sm = doc->state_machines;
/* process the top graph element only */
if(cyberiada_get_attr_value(buffer, buffer_len,
xml_node,
@@ -1218,6 +1256,7 @@ static GraphProcessorState handle_new_graph(xmlNode* xml_node,
return gpsInvalid;
}
/* DEBUG("found graph %s \n", buffer); */
while (sm->next) sm = sm->next;
if (sm->nodes == NULL) {
sm->nodes = cyberiada_new_node(CYBERIADA_ROOT_NODE);
sm->nodes->type = cybNodeSM;
@@ -1227,7 +1266,7 @@ static GraphProcessorState handle_new_graph(xmlNode* xml_node,
}
static GraphProcessorState handle_new_node(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
CyberiadaNode* node;
@@ -1254,7 +1293,7 @@ static GraphProcessorState handle_new_node(xmlNode* xml_node,
cyberiada_graph_add_sibling_node(parent->children, node);
}
if (*(node->id) != 0 || sm->format) {
if (*(node->id) != 0 || doc->format) {
return gpsNode;
} else {
return gpsFakeNode;
@@ -1262,7 +1301,7 @@ static GraphProcessorState handle_new_node(xmlNode* xml_node,
}
static GraphProcessorState handle_group_node(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
CyberiadaNode* current = node_stack_current_node(stack);
@@ -1275,7 +1314,7 @@ static GraphProcessorState handle_group_node(xmlNode* xml_node,
}
static GraphProcessorState handle_comment_node(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
CyberiadaNode* current = node_stack_current_node(stack);
@@ -1290,7 +1329,7 @@ static GraphProcessorState handle_comment_node(xmlNode* xml_node,
}
static GraphProcessorState handle_generic_node(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
@@ -1379,7 +1418,7 @@ static int cyberiada_xml_read_rect(xmlNode* xml_node,
}
static GraphProcessorState handle_node_geometry(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
CyberiadaNodeType type;
@@ -1407,7 +1446,7 @@ static GraphProcessorState handle_node_geometry(xmlNode* xml_node,
}
static GraphProcessorState handle_property(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
@@ -1424,7 +1463,7 @@ static GraphProcessorState handle_property(xmlNode* xml_node,
}
static GraphProcessorState handle_node_title(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
@@ -1445,7 +1484,7 @@ static GraphProcessorState handle_node_title(xmlNode* xml_node,
}
static GraphProcessorState handle_node_action(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
@@ -1460,12 +1499,12 @@ static GraphProcessorState handle_node_action(xmlNode* xml_node,
/* DEBUG("Set node %s comment text %s\n", current->id, buffer); */
cyberiada_copy_string(&(current->title), &(current->title_len), buffer);
} else {
if (current->action != NULL) {
ERROR("Trying to set node %s action twice\n", current->id);
if (current->actions != NULL) {
ERROR("Trying to set node %s actions twice\n", current->id);
return gpsInvalid;
}
/* DEBUG("Set node %s action %s\n", current->id, buffer); */
if (cyberiada_decode_state_action(buffer, &(current->action)) != CYBERIADA_NO_ERROR) {
if (cyberiada_decode_state_actions(buffer, &(current->actions)) != CYBERIADA_NO_ERROR) {
ERROR("cannot decode node action\n");
return gpsInvalid;
}
@@ -1474,7 +1513,7 @@ static GraphProcessorState handle_node_action(xmlNode* xml_node,
}
static GraphProcessorState handle_new_edge(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
@@ -1483,6 +1522,8 @@ static GraphProcessorState handle_new_edge(xmlNode* xml_node,
size_t source_buffer_len = sizeof(source_buffer) - 1;
char target_buffer[MAX_STR_LEN];
size_t target_buffer_len = sizeof(target_buffer) - 1;
CyberiadaSM* sm = doc->state_machines;
while (sm->next) sm = sm->next;
if(cyberiada_get_attr_value(buffer, buffer_len,
xml_node,
GRAPHML_ID_ATTRIBUTE) != CYBERIADA_NO_ERROR) {
@@ -1505,10 +1546,13 @@ static GraphProcessorState handle_new_edge(xmlNode* xml_node,
}
static GraphProcessorState handle_edge_geometry(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
CyberiadaEdge *current = cyberiada_graph_find_last_edge(sm);
CyberiadaEdge *current;
CyberiadaSM* sm = doc->state_machines;
while (sm->next) sm = sm->next;
current = cyberiada_graph_find_last_edge(sm);
if (current == NULL) {
ERROR("no current edge\n");
return gpsInvalid;
@@ -1533,12 +1577,15 @@ static GraphProcessorState handle_edge_geometry(xmlNode* xml_node,
}
static GraphProcessorState handle_edge_point(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
CyberiadaEdge *current = cyberiada_graph_find_last_edge(sm);
CyberiadaEdge *current;
CyberiadaPoint* p;
CyberiadaPolyline *pl, *last_pl;
CyberiadaSM* sm = doc->state_machines;
while (sm->next) sm = sm->next;
current = cyberiada_graph_find_last_edge(sm);
if (current == NULL) {
ERROR("no current edge\n");
return gpsInvalid;
@@ -1562,12 +1609,14 @@ static GraphProcessorState handle_edge_point(xmlNode* xml_node,
}
static GraphProcessorState handle_edge_label(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
size_t buffer_len = sizeof(buffer) - 1;
CyberiadaEdge *current;
CyberiadaSM* sm = doc->state_machines;
while (sm->next) sm = sm->next;
current = cyberiada_graph_find_last_edge(sm);
if (current == NULL) {
ERROR("no current edge\n");
@@ -1589,7 +1638,7 @@ static GraphProcessorState handle_edge_label(xmlNode* xml_node,
}
static GraphProcessorState handle_new_init_data(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
@@ -1601,9 +1650,9 @@ static GraphProcessorState handle_new_init_data(xmlNode* xml_node,
cyberiada_get_element_text(buffer, buffer_len, xml_node);
if (strcmp(buffer, CYBERIADA_FORMAT_CYBERIADAML) == 0) {
cyberiada_copy_string(&(sm->format), &(sm->format_len),
cyberiada_copy_string(&(doc->format), &(doc->format_len),
CYBERIADA_FORMAT_CYBERIADAML);
/* DEBUG("sm format %s\n", sm->format); */
/* DEBUG("doc format %s\n", doc->format); */
return gpsInit;
} else {
ERROR("Bad Cyberida-GraphML format: %s\n", buffer);
@@ -1615,7 +1664,7 @@ static GraphProcessorState handle_new_init_data(xmlNode* xml_node,
}
static GraphProcessorState handle_new_init_key(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
@@ -1678,7 +1727,7 @@ static GraphProcessorState handle_new_init_key(xmlNode* xml_node,
}
static GraphProcessorState handle_node_data(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
@@ -1707,12 +1756,12 @@ static GraphProcessorState handle_node_data(xmlNode* xml_node,
/* DEBUG("Set node %s title %s\n", current->id, buffer); */
cyberiada_copy_string(&(current->title), &(current->title_len), buffer);
} else {
if (current->action != NULL) {
if (current->actions != NULL) {
ERROR("Trying to set node %s action twice\n", current->id);
return gpsInvalid;
}
/* DEBUG("Set node %s action %s\n", current->id, buffer); */
if (cyberiada_decode_state_action(buffer, &(current->action)) != CYBERIADA_NO_ERROR) {
if (cyberiada_decode_state_actions(buffer, &(current->actions)) != CYBERIADA_NO_ERROR) {
ERROR("cannot decode node action\n");
return gpsInvalid;
}
@@ -1732,7 +1781,7 @@ static GraphProcessorState handle_node_data(xmlNode* xml_node,
}
static GraphProcessorState handle_fake_node_data(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
@@ -1769,12 +1818,14 @@ static GraphProcessorState handle_fake_node_data(xmlNode* xml_node,
}
static GraphProcessorState handle_edge_data(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack)
{
char buffer[MAX_STR_LEN];
size_t buffer_len = sizeof(buffer) - 1;
CyberiadaEdge *current;
CyberiadaSM* sm = doc->state_machines;
while (sm->next) sm = sm->next;
current = cyberiada_graph_find_last_edge(sm);
if (current == NULL) {
ERROR("no current edge\n");
@@ -1808,7 +1859,7 @@ static GraphProcessorState handle_edge_data(xmlNode* xml_node,
}
typedef GraphProcessorState (*Handler)(xmlNode* xml_root,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack);
typedef struct {
@@ -1856,7 +1907,7 @@ static ProcessorTransition cyb_processor_state_table[] = {
const size_t cyb_processor_state_table_size = sizeof(cyb_processor_state_table) / sizeof(ProcessorTransition);
static int dispatch_processor(xmlNode* xml_node,
CyberiadaSM* sm,
CyberiadaDocument* doc,
NodeStack** stack,
GraphProcessorState* gps,
ProcessorTransition* processor_state_table,
@@ -1869,7 +1920,7 @@ static int dispatch_processor(xmlNode* xml_node,
for (i = 0; i < processor_state_table_size; i++) {
if (processor_state_table[i].state == *gps &&
strcmp(xml_element_name, processor_state_table[i].symbol) == 0) {
*gps = (*(processor_state_table[i].handler))(xml_node, sm, stack);
*gps = (*(processor_state_table[i].handler))(xml_node, doc, stack);
return CYBERIADA_NO_ERROR;
}
}
@@ -1877,8 +1928,8 @@ static int dispatch_processor(xmlNode* xml_node,
return CYBERIADA_NOT_FOUND;
}
static int cyberiada_build_graph(xmlNode* xml_root,
CyberiadaSM* sm,
static int cyberiada_build_graphs(xmlNode* xml_root,
CyberiadaDocument* doc,
NodeStack** stack,
GraphProcessorState* gps,
ProcessorTransition* processor_state_table,
@@ -1900,13 +1951,13 @@ static int cyberiada_build_graph(xmlNode* xml_root,
sm->nodes ? sm->nodes->id : "none",
debug_state_names[*gps]); */
node_stack_push(stack);
dispatch_processor(cur_xml_node, sm, stack, gps,
dispatch_processor(cur_xml_node, doc, stack, gps,
processor_state_table, processor_state_table_size);
if (*gps == gpsInvalid) {
return CYBERIADA_FORMAT_ERROR;
}
if (cur_xml_node->children) {
int res = cyberiada_build_graph(cur_xml_node->children, sm, stack, gps,
int res = cyberiada_build_graphs(cur_xml_node->children, doc, stack, gps,
processor_state_table, processor_state_table_size);
if (res != CYBERIADA_NO_ERROR) {
return res;
@@ -1917,7 +1968,7 @@ static int cyberiada_build_graph(xmlNode* xml_root,
return CYBERIADA_NO_ERROR;
}
static int cyberiada_decode_yed_xml(xmlNode* root, CyberiadaSM* sm)
static int cyberiada_decode_yed_xml(xmlNode* root, CyberiadaDocument* doc)
{
char buffer[MAX_STR_LEN];
size_t buffer_len = sizeof(buffer) - 1;
@@ -1930,15 +1981,15 @@ static int cyberiada_decode_yed_xml(xmlNode* root, CyberiadaSM* sm)
if (cyberiada_get_attr_value(buffer, buffer_len,
root,
GRAPHML_BERLOGA_SCHEMENAME_ATTR) == CYBERIADA_NO_ERROR) {
cyberiada_copy_string(&(sm->format), &(sm->format_len), CYBERIADA_FORMAT_BERLOGA);
cyberiada_copy_string(&(doc->format), &(doc->format_len), CYBERIADA_FORMAT_BERLOGA);
berloga_format = 1;
} else {
cyberiada_copy_string(&(sm->format), &(sm->format_len), CYBERIADA_FORMAT_OSTRANNA);
cyberiada_copy_string(&(doc->format), &(doc->format_len), CYBERIADA_FORMAT_OSTRANNA);
berloga_format = 0;
}
/* DEBUG("sm format %s\n", sm->format); */
/* DEBUG("doc format %s\n", doc->format); */
if ((res = cyberiada_build_graph(root, sm, &stack, &gps,
if ((res = cyberiada_build_graphs(root, doc, &stack, &gps,
yed_processor_state_table,
yed_processor_state_table_size)) != CYBERIADA_NO_ERROR) {
return res;
@@ -1950,22 +2001,22 @@ static int cyberiada_decode_yed_xml(xmlNode* root, CyberiadaSM* sm)
}
if (berloga_format) {
cyberiada_add_default_meta(sm, buffer);
cyberiada_add_default_meta(doc, buffer);
} else {
if (sm->nodes) {
node = cyberiada_graph_find_node_by_type(sm->nodes, cybNodeCompositeState);
if (doc->state_machines->nodes) {
node = cyberiada_graph_find_node_by_type(doc->state_machines->nodes, cybNodeCompositeState);
}
if (node) {
cyberiada_add_default_meta(sm, node->title);
cyberiada_add_default_meta(doc, node->title);
} else {
cyberiada_add_default_meta(sm, EMPTY_TITLE);
cyberiada_add_default_meta(doc, EMPTY_TITLE);
}
}
return CYBERIADA_NO_ERROR;
}
static int cyberiada_decode_cyberiada_xml(xmlNode* root, CyberiadaSM* sm)
static int cyberiada_decode_cyberiada_xml(xmlNode* root, CyberiadaDocument* doc)
{
GraphProcessorState gps = gpsInit;
NodeStack* stack = NULL;
@@ -1973,7 +2024,7 @@ static int cyberiada_decode_cyberiada_xml(xmlNode* root, CyberiadaSM* sm)
/* CyberiadaNode *meta_node, *ext_node;
CyberiadaEdge *edge, *prev_edge;*/
if ((res = cyberiada_build_graph(root, sm, &stack, &gps,
if ((res = cyberiada_build_graphs(root, doc, &stack, &gps,
cyb_processor_state_table,
cyb_processor_state_table_size)) != CYBERIADA_NO_ERROR) {
return res;
@@ -2060,13 +2111,13 @@ static int cyberiada_check_graphml_ns(xmlNode* root, CyberiadaXMLFormat* format)
return CYBERIADA_NO_ERROR;
}
int cyberiada_read_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat format)
int cyberiada_read_sm_document(CyberiadaDocument* cyb_doc, const char* filename, CyberiadaXMLFormat format)
{
int res;
xmlDoc* doc = NULL;
xmlNode* root = NULL;
cyberiada_init_sm(sm);
cyberiada_init_sm_document(cyb_doc);
/* parse the file and get the DOM */
if ((doc = xmlReadFile(filename, NULL, 0)) == NULL) {
@@ -2093,11 +2144,13 @@ int cyberiada_read_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat
break;
}
cyb_doc->state_machines = cyberiada_create_sm();
/* DEBUG("reading format %d\n", format); */
if (format == cybxmlYED) {
res = cyberiada_decode_yed_xml(root, sm);
res = cyberiada_decode_yed_xml(root, cyb_doc);
} else if (format == cybxmlCyberiada) {
res = cyberiada_decode_cyberiada_xml(root, sm);
res = cyberiada_decode_cyberiada_xml(root, cyb_doc);
} else {
ERROR("error: unsupported GraphML format of file %s\n",
filename);
@@ -2109,7 +2162,7 @@ int cyberiada_read_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat
break;
}
if ((res = cyberiada_graph_reconstruct_edges(sm)) != CYBERIADA_NO_ERROR) {
if ((res = cyberiada_graphs_reconstruct_edges(cyb_doc)) != CYBERIADA_NO_ERROR) {
ERROR("error: cannot reconstruct graph edges from file %s\n",
filename);
break;
@@ -2199,7 +2252,7 @@ static int cyberiada_print_node(CyberiadaNode* node, int level)
node->geometry_rect->height);
}
cyberiada_print_action(node->action, level + 1);
cyberiada_print_action(node->actions, level + 1);
printf("%sChildren:\n", levelspace);
for (cur_node = node->children; cur_node; cur_node = cur_node->next) {
@@ -2262,14 +2315,13 @@ static int cyberiada_print_edge(CyberiadaEdge* edge)
return CYBERIADA_NO_ERROR;
}*/
int cyberiada_print_sm(CyberiadaSM* sm)
static int cyberiada_print_sm(CyberiadaSM* sm)
{
CyberiadaNode* cur_node;
CyberiadaEdge* cur_edge;
/*CyberiadaExtension* cur_ext;*/
printf("\nState Machine [%s]\n", sm->format);
cyberiada_print_meta(sm->meta_info);
printf("State Machine\n");
printf("Nodes:\n");
for (cur_node = sm->nodes; cur_node; cur_node = cur_node->next) {
@@ -2294,6 +2346,20 @@ int cyberiada_print_sm(CyberiadaSM* sm)
return CYBERIADA_NO_ERROR;
}
int cyberiada_print_sm_document(CyberiadaDocument* doc)
{
CyberiadaSM* sm;
printf("\nDocument:\n");
cyberiada_print_meta(doc->meta_info);
for (sm = doc->state_machines; sm; sm = sm->next) {
cyberiada_print_sm(sm);
}
return CYBERIADA_NO_ERROR;
}
#define INDENT_STR " "
#define XML_WRITE_OPEN_E(w, e) if ((res = xmlTextWriterStartElement(w, (const xmlChar *)e)) < 0) { \
fprintf(stderr, "xml open element error %d at %s:%d", res, __FILE__, __LINE__); \
@@ -2349,7 +2415,7 @@ typedef struct {
const char* attr_yfiles;
} GraphMLKey;
static int cyberiada_write_sm_cyberiada(CyberiadaSM* sm, xmlTextWriterPtr writer)
static int cyberiada_write_sm_document_cyberiada(CyberiadaDocument* doc, xmlTextWriterPtr writer)
{
return CYBERIADA_NO_ERROR;
}
@@ -2647,7 +2713,7 @@ static int cyberiada_write_node_yed(xmlTextWriterPtr writer, CyberiadaNode* node
return CYBERIADA_XML_ERROR;
}
if (cyberiada_write_node_action_yed(writer, node->action, indent + 3) != CYBERIADA_NO_ERROR) {
if (cyberiada_write_node_action_yed(writer, node->actions, indent + 3) != CYBERIADA_NO_ERROR) {
ERROR("error while writing simple node action\n");
return CYBERIADA_XML_ERROR;
}
@@ -2688,7 +2754,7 @@ static int cyberiada_write_node_yed(xmlTextWriterPtr writer, CyberiadaNode* node
return CYBERIADA_XML_ERROR;
}
if (cyberiada_write_node_action_yed(writer, node->action, indent + 5) != CYBERIADA_NO_ERROR) {
if (cyberiada_write_node_action_yed(writer, node->actions, indent + 5) != CYBERIADA_NO_ERROR) {
ERROR("error while writing composite node action\n");
return CYBERIADA_XML_ERROR;
}
@@ -2796,13 +2862,14 @@ static GraphMLKey yed_graphml_keys[] = {
};
const size_t yed_graphml_keys_count = sizeof(yed_graphml_keys) / sizeof(GraphMLKey);
static int cyberiada_write_sm_yed(CyberiadaSM* sm, xmlTextWriterPtr writer)
static int cyberiada_write_sm_document_yed(CyberiadaDocument* doc, xmlTextWriterPtr writer)
{
size_t i;
int res;
GraphMLKey* key;
CyberiadaNode* cur_node;
CyberiadaEdge* cur_edge;
CyberiadaSM* sm = doc->state_machines;
XML_WRITE_OPEN_E(writer, GRAPHML_GRAPHML_ELEMENT);
@@ -2811,8 +2878,8 @@ static int cyberiada_write_sm_yed(CyberiadaSM* sm, xmlTextWriterPtr writer)
XML_WRITE_ATTR(writer, yed_graphml_attributes[i], yed_graphml_attributes[i + 1]);
}
/* add scheme name if it is available */
if (sm->meta_info && sm->meta_info->name && *sm->meta_info->name) {
XML_WRITE_ATTR(writer, GRAPHML_BERLOGA_SCHEMENAME_ATTR, sm->meta_info->name);
if (doc->meta_info && doc->meta_info->name && *doc->meta_info->name) {
XML_WRITE_ATTR(writer, GRAPHML_BERLOGA_SCHEMENAME_ATTR, doc->meta_info->name);
}
/* write graphml keys */
@@ -2865,7 +2932,7 @@ static int cyberiada_write_sm_yed(CyberiadaSM* sm, xmlTextWriterPtr writer)
return CYBERIADA_NO_ERROR;
}
int cyberiada_write_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat format)
int cyberiada_write_sm_document(CyberiadaDocument* doc, const char* filename, CyberiadaXMLFormat format)
{
xmlTextWriterPtr writer;
int res;
@@ -2875,8 +2942,8 @@ int cyberiada_write_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat
return CYBERIADA_BAD_PARAMETER;
}
if (!sm) {
ERROR("empty SM to write\n");
if (!doc) {
ERROR("empty SM document to write\n");
return CYBERIADA_BAD_PARAMETER;
}
@@ -2894,9 +2961,14 @@ int cyberiada_write_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat
}
if (format == cybxmlYED) {
res = cyberiada_write_sm_yed(sm, writer);
if (!doc->state_machines || doc->state_machines->next) {
ERROR("YED format supports only single SM documents\n");
xmlFreeTextWriter(writer);
return CYBERIADA_BAD_PARAMETER;
}
res = cyberiada_write_sm_document_yed(doc, writer);
} else if (format == cybxmlCyberiada) {
res = cyberiada_write_sm_cyberiada(sm, writer);
res = cyberiada_write_sm_document_cyberiada(doc, writer);
}
if (res != CYBERIADA_NO_ERROR) {
ERROR("error writing xml %d\n", res);

View File

@@ -40,12 +40,8 @@ typedef enum {
cybNodeComment = 8, /* comment node */
cybNodeMachineComment = 16, /* machine-readable comment node */
cybNodeInitial = 32, /* initial pseudostate */
cybNodeFinal = 64, /* final pseudostate */
cybNodeChoice = 128, /* final pseudostate */
cybNodeEntry = 256, /* entry pseudostate */
cybNodeExit = 512, /* exit pseudostate */
cybNodeShallowHistory = 1024, /* shallow history pseudostate */
cybNodeTerminate = 2048, /* terminate pseudostate */
cybNodeFinal = 64, /* final state */
cybNodeChoice = 128, /* choice pseudostate */
} CyberiadaNodeType;
typedef unsigned int CyberiadaNodeTypeMask;
@@ -98,7 +94,7 @@ typedef struct _CyberiadaNode {
size_t id_len;
char* title;
size_t title_len;
CyberiadaAction* action;
CyberiadaAction* actions;
CyberiadaRect* geometry_rect;
struct _CyberiadaNode* next;
struct _CyberiadaNode* parent;
@@ -126,48 +122,67 @@ typedef struct _CyberiadaEdge {
struct _CyberiadaEdge* next;
} CyberiadaEdge;
/* SM metainformation */
typedef struct {
char* standard_version; /* HSM standard version (required parameter) */
size_t standard_version_len;
char* platform_name; /* target platform name */
size_t platform_name_len;
char* platform_version; /* target platform version */
size_t platform_version_len;
char* platform_language; /* target platform language */
size_t platform_language_len;
char* target_system; /* target system controlled by the SM */
size_t target_system_len;
char* name; /* document name */
size_t name_len;
char* author; /* document author */
size_t author_len;
char* contact; /* document author's contact */
size_t contact_len;
char* description; /* document description */
size_t description_len;
char* version; /* document version */
size_t version_len;
char* date; /* document date */
size_t date_len;
char actions_order_flag; /* actions order flag (0 = not set, 1 = transition first, 2 = exit first) */
char event_propagation_flag; /* event propagation flag (0 = not set, 1 = block events, 2 = propagate events) */
} CyberiadaMetainformation;
/* SM graph (state machine) */
typedef struct {
char* format; /* SM graph format string */
size_t format_len; /* SM graph format string length */
CyberiadaMetainformation* meta_info;
typedef struct _CyberiadaSM {
CyberiadaNode* nodes;
CyberiadaEdge* edges;
struct _CyberiadaSM* next;
} CyberiadaSM;
/* SM metainformation */
typedef struct {
/* HSM standard version (required parameter) */
char* standard_version;
size_t standard_version_len;
/* target platform name */
char* platform_name;
size_t platform_name_len;
/* target platform version */
char* platform_version;
size_t platform_version_len;
/* target platform language */
char* platform_language;
size_t platform_language_len;
/* target system controlled by the SM */
char* target_system;
size_t target_system_len;
/* document name */
char* name;
size_t name_len;
/* document author */
char* author;
size_t author_len;
/* document author's contact */
char* contact;
size_t contact_len;
/* document description */
char* description;
size_t description_len;
/* document version */
char* version;
size_t version_len;
/* document date */
char* date;
size_t date_len;
/* actions order flag (0 = not set, 1 = transition first, 2 = exit first) */
char actions_order_flag;
/* event propagation flag (0 = not set, 1 = block events, 2 = propagate events) */
char event_propagation_flag;
} CyberiadaMetainformation;
/* SM document */
typedef struct {
char* format; /* SM document format string */
size_t format_len; /* SM document format string length */
CyberiadaMetainformation* meta_info; /* SM document metainformation */
CyberiadaSM* state_machines; /* State machines */
} CyberiadaDocument;
/* SM GraphML supported formats */
typedef enum {
cybxmlCyberiada = 0,
cybxmlYED,
cybxmlUnknown
cybxmlYED = 1,
cybxmlUnknown = 2
} CyberiadaXMLFormat;
/* -----------------------------------------------------------------------------
@@ -188,28 +203,28 @@ typedef enum {
* ----------------------------------------------------------------------------- */
/* Allocate the SM structure in memory (for heap usage) */
CyberiadaSM* cyberiada_create_sm(void);
CyberiadaDocument* cyberiada_create_sm_document(void);
/* Initialize the SM structure */
/* Do not use the structure before the initialization! */
int cyberiada_init_sm(CyberiadaSM* sm);
int cyberiada_init_sm_document(CyberiadaDocument* doc);
/* Cleanup the content of the SM structure */
/* Free the allocated memory of the structure content but not the structure itself */
int cyberiada_cleanup_sm(CyberiadaSM* sm);
int cyberiada_cleanup_sm_document(CyberiadaDocument* doc);
/* Free the allocated SM structure with the content (for heap usage) */
int cyberiada_destroy_sm(CyberiadaSM* sm);
int cyberiada_destroy_sm_document(CyberiadaDocument* doc);
/* Read an XML file and decode the SM structure */
/* Allocate the SM structure first */
int cyberiada_read_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat format);
/* Allocate the SM document structure first */
int cyberiada_read_sm_document(CyberiadaDocument* doc, const char* filename, CyberiadaXMLFormat format);
/* Encode the SM structure and write the data to an XML file */
int cyberiada_write_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat format);
/* Encode the SM document structure and write the data to an XML file */
int cyberiada_write_sm_document(CyberiadaDocument* doc, const char* filename, CyberiadaXMLFormat format);
/* Print the SM structure to stdout */
int cyberiada_print_sm(CyberiadaSM* sm);
int cyberiada_print_sm_document(CyberiadaDocument* doc);
#ifdef __cplusplus
}

10
test.c
View File

@@ -71,7 +71,7 @@ int main(int argc, char** argv)
CyberiadaXMLFormat source_format = cybxmlUnknown, dest_format = cybxmlUnknown;
unsigned int i;
int res;
CyberiadaSM sm;
CyberiadaDocument doc;
char print = 0;
if (argc < 3) {
@@ -172,23 +172,23 @@ int main(int argc, char** argv)
}
}
if ((res = cyberiada_read_sm(&sm, source_filename, source_format)) != CYBERIADA_NO_ERROR) {
if ((res = cyberiada_read_sm_document(&doc, source_filename, source_format)) != CYBERIADA_NO_ERROR) {
fprintf(stderr, "error while reading %s file: %d\n",
source_filename, res);
return 2;
}
if (print) {
cyberiada_print_sm(&sm);
cyberiada_print_sm_document(&doc);
} else {
if ((res = cyberiada_write_sm(&sm, dest_filename, dest_format)) != CYBERIADA_NO_ERROR) {
if ((res = cyberiada_write_sm_document(&doc, dest_filename, dest_format)) != CYBERIADA_NO_ERROR) {
fprintf(stderr, "error while writing %s file: %d\n",
dest_filename, res);
return 3;
}
}
cyberiada_cleanup_sm(&sm);
cyberiada_cleanup_sm_document(&doc);
return 0;
}