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->type = cybNodeSimpleState;
new_node->title = NULL; new_node->title = NULL;
new_node->title_len = 0; new_node->title_len = 0;
new_node->action = NULL; new_node->actions = NULL;
new_node->next = NULL; new_node->next = NULL;
new_node->parent = NULL; new_node->parent = NULL;
new_node->children = NULL; new_node->children = NULL;
@@ -277,7 +277,7 @@ static int cyberiada_destroy_node(CyberiadaNode* node)
if(node->children) { if(node->children) {
cyberiada_destroy_all_nodes(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); if(node->geometry_rect) free(node->geometry_rect);
free(node); free(node);
} }
@@ -554,7 +554,7 @@ static int cyberiada_decode_state_block_action(const char* text, CyberiadaAction
return CYBERIADA_NO_ERROR; 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; int res;
size_t buffer_len; size_t buffer_len;
@@ -769,9 +769,12 @@ static int cyberiada_destroy_edge(CyberiadaEdge* e)
return CYBERIADA_NO_ERROR; 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) { while (edge) {
CyberiadaNode* source = cyberiada_graph_find_node_by_id(sm->nodes, edge->source_id); 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); 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->target = target;
edge = edge->next; edge = edge->next;
} }
}
return CYBERIADA_NO_ERROR; 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; CyberiadaMetainformation* meta;
if (sm->meta_info) { if (doc->meta_info) {
return CYBERIADA_BAD_PARAMETER; 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->actions_order_flag = 1;
meta->event_propagation_flag = 1; meta->event_propagation_flag = 1;
sm->meta_info = meta; doc->meta_info = meta;
return CYBERIADA_NO_ERROR; 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 * 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)); CyberiadaSM* sm = (CyberiadaSM*)malloc(sizeof(CyberiadaSM));
cyberiada_init_sm(sm); cyberiada_init_sm(sm);
return sm; return sm;
} }
int cyberiada_init_sm(CyberiadaSM* sm) CyberiadaDocument* cyberiada_create_sm_document(void)
{ {
if (sm) { CyberiadaDocument* doc = (CyberiadaDocument*)malloc(sizeof(CyberiadaDocument));
sm->format = NULL; cyberiada_init_sm_document(doc);
sm->meta_info = NULL; return doc;
sm->nodes = NULL; }
sm->edges = NULL;
int cyberiada_init_sm_document(CyberiadaDocument* doc)
{
if (doc) {
doc->format = NULL;
doc->meta_info = NULL;
doc->state_machines = NULL;
} }
return CYBERIADA_NO_ERROR; return CYBERIADA_NO_ERROR;
} }
int cyberiada_cleanup_sm(CyberiadaSM* sm) static int cyberiada_destroy_sm(CyberiadaSM* sm)
{ {
CyberiadaEdge *edge, *e; CyberiadaEdge *edge, *e;
if (sm) { if (sm) {
if (sm->format) {
free(sm->format);
}
if (sm->meta_info) {
cyberiada_destroy_meta(sm->meta_info);
}
if (sm->nodes) { if (sm->nodes) {
cyberiada_destroy_all_nodes(sm->nodes); cyberiada_destroy_all_nodes(sm->nodes);
} }
@@ -1047,18 +1061,41 @@ int cyberiada_cleanup_sm(CyberiadaSM* sm)
cyberiada_destroy_edge(e); cyberiada_destroy_edge(e);
} while (edge); } while (edge);
} }
cyberiada_init_sm(sm); free(sm);
} }
return CYBERIADA_NO_ERROR; 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) { if (res != CYBERIADA_NO_ERROR) {
return res; return res;
} }
free(sm); free(doc);
return CYBERIADA_NO_ERROR; 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, static GraphProcessorState handle_new_graph(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; char buffer[MAX_STR_LEN];
size_t buffer_len = sizeof(buffer) - 1; size_t buffer_len = sizeof(buffer) - 1;
CyberiadaSM* sm = doc->state_machines;
/* process the top graph element only */ /* process the top graph element only */
if(cyberiada_get_attr_value(buffer, buffer_len, if(cyberiada_get_attr_value(buffer, buffer_len,
xml_node, xml_node,
@@ -1218,6 +1256,7 @@ static GraphProcessorState handle_new_graph(xmlNode* xml_node,
return gpsInvalid; return gpsInvalid;
} }
/* DEBUG("found graph %s \n", buffer); */ /* DEBUG("found graph %s \n", buffer); */
while (sm->next) sm = sm->next;
if (sm->nodes == NULL) { if (sm->nodes == NULL) {
sm->nodes = cyberiada_new_node(CYBERIADA_ROOT_NODE); sm->nodes = cyberiada_new_node(CYBERIADA_ROOT_NODE);
sm->nodes->type = cybNodeSM; sm->nodes->type = cybNodeSM;
@@ -1227,7 +1266,7 @@ static GraphProcessorState handle_new_graph(xmlNode* xml_node,
} }
static GraphProcessorState handle_new_node(xmlNode* xml_node, static GraphProcessorState handle_new_node(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
CyberiadaNode* node; CyberiadaNode* node;
@@ -1254,7 +1293,7 @@ static GraphProcessorState handle_new_node(xmlNode* xml_node,
cyberiada_graph_add_sibling_node(parent->children, node); cyberiada_graph_add_sibling_node(parent->children, node);
} }
if (*(node->id) != 0 || sm->format) { if (*(node->id) != 0 || doc->format) {
return gpsNode; return gpsNode;
} else { } else {
return gpsFakeNode; return gpsFakeNode;
@@ -1262,7 +1301,7 @@ static GraphProcessorState handle_new_node(xmlNode* xml_node,
} }
static GraphProcessorState handle_group_node(xmlNode* xml_node, static GraphProcessorState handle_group_node(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
CyberiadaNode* current = node_stack_current_node(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, static GraphProcessorState handle_comment_node(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
CyberiadaNode* current = node_stack_current_node(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, static GraphProcessorState handle_generic_node(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; 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, static GraphProcessorState handle_node_geometry(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
CyberiadaNodeType type; CyberiadaNodeType type;
@@ -1407,7 +1446,7 @@ static GraphProcessorState handle_node_geometry(xmlNode* xml_node,
} }
static GraphProcessorState handle_property(xmlNode* xml_node, static GraphProcessorState handle_property(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; char buffer[MAX_STR_LEN];
@@ -1424,7 +1463,7 @@ static GraphProcessorState handle_property(xmlNode* xml_node,
} }
static GraphProcessorState handle_node_title(xmlNode* xml_node, static GraphProcessorState handle_node_title(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; 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, static GraphProcessorState handle_node_action(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; 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); */ /* DEBUG("Set node %s comment text %s\n", current->id, buffer); */
cyberiada_copy_string(&(current->title), &(current->title_len), buffer); cyberiada_copy_string(&(current->title), &(current->title_len), buffer);
} else { } else {
if (current->action != NULL) { if (current->actions != NULL) {
ERROR("Trying to set node %s action twice\n", current->id); ERROR("Trying to set node %s actions twice\n", current->id);
return gpsInvalid; return gpsInvalid;
} }
/* DEBUG("Set node %s action %s\n", current->id, buffer); */ /* 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"); ERROR("cannot decode node action\n");
return gpsInvalid; return gpsInvalid;
} }
@@ -1474,7 +1513,7 @@ static GraphProcessorState handle_node_action(xmlNode* xml_node,
} }
static GraphProcessorState handle_new_edge(xmlNode* xml_node, static GraphProcessorState handle_new_edge(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; 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; size_t source_buffer_len = sizeof(source_buffer) - 1;
char target_buffer[MAX_STR_LEN]; char target_buffer[MAX_STR_LEN];
size_t target_buffer_len = sizeof(target_buffer) - 1; 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, if(cyberiada_get_attr_value(buffer, buffer_len,
xml_node, xml_node,
GRAPHML_ID_ATTRIBUTE) != CYBERIADA_NO_ERROR) { 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, static GraphProcessorState handle_edge_geometry(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) 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) { if (current == NULL) {
ERROR("no current edge\n"); ERROR("no current edge\n");
return gpsInvalid; return gpsInvalid;
@@ -1533,12 +1577,15 @@ static GraphProcessorState handle_edge_geometry(xmlNode* xml_node,
} }
static GraphProcessorState handle_edge_point(xmlNode* xml_node, static GraphProcessorState handle_edge_point(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
CyberiadaEdge *current = cyberiada_graph_find_last_edge(sm); CyberiadaEdge *current;
CyberiadaPoint* p; CyberiadaPoint* p;
CyberiadaPolyline *pl, *last_pl; 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) { if (current == NULL) {
ERROR("no current edge\n"); ERROR("no current edge\n");
return gpsInvalid; return gpsInvalid;
@@ -1562,12 +1609,14 @@ static GraphProcessorState handle_edge_point(xmlNode* xml_node,
} }
static GraphProcessorState handle_edge_label(xmlNode* xml_node, static GraphProcessorState handle_edge_label(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; char buffer[MAX_STR_LEN];
size_t buffer_len = sizeof(buffer) - 1; size_t buffer_len = sizeof(buffer) - 1;
CyberiadaEdge *current; CyberiadaEdge *current;
CyberiadaSM* sm = doc->state_machines;
while (sm->next) sm = sm->next;
current = cyberiada_graph_find_last_edge(sm); current = cyberiada_graph_find_last_edge(sm);
if (current == NULL) { if (current == NULL) {
ERROR("no current edge\n"); 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, static GraphProcessorState handle_new_init_data(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; 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); cyberiada_get_element_text(buffer, buffer_len, xml_node);
if (strcmp(buffer, CYBERIADA_FORMAT_CYBERIADAML) == 0) { 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); CYBERIADA_FORMAT_CYBERIADAML);
/* DEBUG("sm format %s\n", sm->format); */ /* DEBUG("doc format %s\n", doc->format); */
return gpsInit; return gpsInit;
} else { } else {
ERROR("Bad Cyberida-GraphML format: %s\n", buffer); 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, static GraphProcessorState handle_new_init_key(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; 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, static GraphProcessorState handle_node_data(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; 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); */ /* DEBUG("Set node %s title %s\n", current->id, buffer); */
cyberiada_copy_string(&(current->title), &(current->title_len), buffer); cyberiada_copy_string(&(current->title), &(current->title_len), buffer);
} else { } else {
if (current->action != NULL) { if (current->actions != NULL) {
ERROR("Trying to set node %s action twice\n", current->id); ERROR("Trying to set node %s action twice\n", current->id);
return gpsInvalid; return gpsInvalid;
} }
/* DEBUG("Set node %s action %s\n", current->id, buffer); */ /* 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"); ERROR("cannot decode node action\n");
return gpsInvalid; return gpsInvalid;
} }
@@ -1732,7 +1781,7 @@ static GraphProcessorState handle_node_data(xmlNode* xml_node,
} }
static GraphProcessorState handle_fake_node_data(xmlNode* xml_node, static GraphProcessorState handle_fake_node_data(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; 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, static GraphProcessorState handle_edge_data(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack) NodeStack** stack)
{ {
char buffer[MAX_STR_LEN]; char buffer[MAX_STR_LEN];
size_t buffer_len = sizeof(buffer) - 1; size_t buffer_len = sizeof(buffer) - 1;
CyberiadaEdge *current; CyberiadaEdge *current;
CyberiadaSM* sm = doc->state_machines;
while (sm->next) sm = sm->next;
current = cyberiada_graph_find_last_edge(sm); current = cyberiada_graph_find_last_edge(sm);
if (current == NULL) { if (current == NULL) {
ERROR("no current edge\n"); ERROR("no current edge\n");
@@ -1808,7 +1859,7 @@ static GraphProcessorState handle_edge_data(xmlNode* xml_node,
} }
typedef GraphProcessorState (*Handler)(xmlNode* xml_root, typedef GraphProcessorState (*Handler)(xmlNode* xml_root,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack); NodeStack** stack);
typedef struct { 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); const size_t cyb_processor_state_table_size = sizeof(cyb_processor_state_table) / sizeof(ProcessorTransition);
static int dispatch_processor(xmlNode* xml_node, static int dispatch_processor(xmlNode* xml_node,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack, NodeStack** stack,
GraphProcessorState* gps, GraphProcessorState* gps,
ProcessorTransition* processor_state_table, ProcessorTransition* processor_state_table,
@@ -1869,7 +1920,7 @@ static int dispatch_processor(xmlNode* xml_node,
for (i = 0; i < processor_state_table_size; i++) { for (i = 0; i < processor_state_table_size; i++) {
if (processor_state_table[i].state == *gps && if (processor_state_table[i].state == *gps &&
strcmp(xml_element_name, processor_state_table[i].symbol) == 0) { 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; return CYBERIADA_NO_ERROR;
} }
} }
@@ -1877,8 +1928,8 @@ static int dispatch_processor(xmlNode* xml_node,
return CYBERIADA_NOT_FOUND; return CYBERIADA_NOT_FOUND;
} }
static int cyberiada_build_graph(xmlNode* xml_root, static int cyberiada_build_graphs(xmlNode* xml_root,
CyberiadaSM* sm, CyberiadaDocument* doc,
NodeStack** stack, NodeStack** stack,
GraphProcessorState* gps, GraphProcessorState* gps,
ProcessorTransition* processor_state_table, ProcessorTransition* processor_state_table,
@@ -1900,13 +1951,13 @@ static int cyberiada_build_graph(xmlNode* xml_root,
sm->nodes ? sm->nodes->id : "none", sm->nodes ? sm->nodes->id : "none",
debug_state_names[*gps]); */ debug_state_names[*gps]); */
node_stack_push(stack); 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); processor_state_table, processor_state_table_size);
if (*gps == gpsInvalid) { if (*gps == gpsInvalid) {
return CYBERIADA_FORMAT_ERROR; return CYBERIADA_FORMAT_ERROR;
} }
if (cur_xml_node->children) { 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); processor_state_table, processor_state_table_size);
if (res != CYBERIADA_NO_ERROR) { if (res != CYBERIADA_NO_ERROR) {
return res; return res;
@@ -1917,7 +1968,7 @@ static int cyberiada_build_graph(xmlNode* xml_root,
return CYBERIADA_NO_ERROR; 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]; char buffer[MAX_STR_LEN];
size_t buffer_len = sizeof(buffer) - 1; 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, if (cyberiada_get_attr_value(buffer, buffer_len,
root, root,
GRAPHML_BERLOGA_SCHEMENAME_ATTR) == CYBERIADA_NO_ERROR) { 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; berloga_format = 1;
} else { } 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; 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,
yed_processor_state_table_size)) != CYBERIADA_NO_ERROR) { yed_processor_state_table_size)) != CYBERIADA_NO_ERROR) {
return res; return res;
@@ -1950,22 +2001,22 @@ static int cyberiada_decode_yed_xml(xmlNode* root, CyberiadaSM* sm)
} }
if (berloga_format) { if (berloga_format) {
cyberiada_add_default_meta(sm, buffer); cyberiada_add_default_meta(doc, buffer);
} else { } else {
if (sm->nodes) { if (doc->state_machines->nodes) {
node = cyberiada_graph_find_node_by_type(sm->nodes, cybNodeCompositeState); node = cyberiada_graph_find_node_by_type(doc->state_machines->nodes, cybNodeCompositeState);
} }
if (node) { if (node) {
cyberiada_add_default_meta(sm, node->title); cyberiada_add_default_meta(doc, node->title);
} else { } else {
cyberiada_add_default_meta(sm, EMPTY_TITLE); cyberiada_add_default_meta(doc, EMPTY_TITLE);
} }
} }
return CYBERIADA_NO_ERROR; 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; GraphProcessorState gps = gpsInit;
NodeStack* stack = NULL; NodeStack* stack = NULL;
@@ -1973,7 +2024,7 @@ static int cyberiada_decode_cyberiada_xml(xmlNode* root, CyberiadaSM* sm)
/* CyberiadaNode *meta_node, *ext_node; /* CyberiadaNode *meta_node, *ext_node;
CyberiadaEdge *edge, *prev_edge;*/ 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,
cyb_processor_state_table_size)) != CYBERIADA_NO_ERROR) { cyb_processor_state_table_size)) != CYBERIADA_NO_ERROR) {
return res; return res;
@@ -2060,13 +2111,13 @@ static int cyberiada_check_graphml_ns(xmlNode* root, CyberiadaXMLFormat* format)
return CYBERIADA_NO_ERROR; 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; int res;
xmlDoc* doc = NULL; xmlDoc* doc = NULL;
xmlNode* root = NULL; xmlNode* root = NULL;
cyberiada_init_sm(sm); cyberiada_init_sm_document(cyb_doc);
/* parse the file and get the DOM */ /* parse the file and get the DOM */
if ((doc = xmlReadFile(filename, NULL, 0)) == NULL) { if ((doc = xmlReadFile(filename, NULL, 0)) == NULL) {
@@ -2093,11 +2144,13 @@ int cyberiada_read_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat
break; break;
} }
cyb_doc->state_machines = cyberiada_create_sm();
/* DEBUG("reading format %d\n", format); */ /* DEBUG("reading format %d\n", format); */
if (format == cybxmlYED) { if (format == cybxmlYED) {
res = cyberiada_decode_yed_xml(root, sm); res = cyberiada_decode_yed_xml(root, cyb_doc);
} else if (format == cybxmlCyberiada) { } else if (format == cybxmlCyberiada) {
res = cyberiada_decode_cyberiada_xml(root, sm); res = cyberiada_decode_cyberiada_xml(root, cyb_doc);
} else { } else {
ERROR("error: unsupported GraphML format of file %s\n", ERROR("error: unsupported GraphML format of file %s\n",
filename); filename);
@@ -2109,7 +2162,7 @@ int cyberiada_read_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat
break; 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", ERROR("error: cannot reconstruct graph edges from file %s\n",
filename); filename);
break; break;
@@ -2199,7 +2252,7 @@ static int cyberiada_print_node(CyberiadaNode* node, int level)
node->geometry_rect->height); node->geometry_rect->height);
} }
cyberiada_print_action(node->action, level + 1); cyberiada_print_action(node->actions, level + 1);
printf("%sChildren:\n", levelspace); printf("%sChildren:\n", levelspace);
for (cur_node = node->children; cur_node; cur_node = cur_node->next) { 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; return CYBERIADA_NO_ERROR;
}*/ }*/
int cyberiada_print_sm(CyberiadaSM* sm) static int cyberiada_print_sm(CyberiadaSM* sm)
{ {
CyberiadaNode* cur_node; CyberiadaNode* cur_node;
CyberiadaEdge* cur_edge; CyberiadaEdge* cur_edge;
/*CyberiadaExtension* cur_ext;*/ /*CyberiadaExtension* cur_ext;*/
printf("\nState Machine [%s]\n", sm->format); printf("State Machine\n");
cyberiada_print_meta(sm->meta_info);
printf("Nodes:\n"); printf("Nodes:\n");
for (cur_node = sm->nodes; cur_node; cur_node = cur_node->next) { 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; 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 INDENT_STR " "
#define XML_WRITE_OPEN_E(w, e) if ((res = xmlTextWriterStartElement(w, (const xmlChar *)e)) < 0) { \ #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__); \ fprintf(stderr, "xml open element error %d at %s:%d", res, __FILE__, __LINE__); \
@@ -2349,7 +2415,7 @@ typedef struct {
const char* attr_yfiles; const char* attr_yfiles;
} GraphMLKey; } 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; return CYBERIADA_NO_ERROR;
} }
@@ -2647,7 +2713,7 @@ static int cyberiada_write_node_yed(xmlTextWriterPtr writer, CyberiadaNode* node
return CYBERIADA_XML_ERROR; 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"); ERROR("error while writing simple node action\n");
return CYBERIADA_XML_ERROR; return CYBERIADA_XML_ERROR;
} }
@@ -2688,7 +2754,7 @@ static int cyberiada_write_node_yed(xmlTextWriterPtr writer, CyberiadaNode* node
return CYBERIADA_XML_ERROR; 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"); ERROR("error while writing composite node action\n");
return CYBERIADA_XML_ERROR; 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); 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; size_t i;
int res; int res;
GraphMLKey* key; GraphMLKey* key;
CyberiadaNode* cur_node; CyberiadaNode* cur_node;
CyberiadaEdge* cur_edge; CyberiadaEdge* cur_edge;
CyberiadaSM* sm = doc->state_machines;
XML_WRITE_OPEN_E(writer, GRAPHML_GRAPHML_ELEMENT); 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]); XML_WRITE_ATTR(writer, yed_graphml_attributes[i], yed_graphml_attributes[i + 1]);
} }
/* add scheme name if it is available */ /* add scheme name if it is available */
if (sm->meta_info && sm->meta_info->name && *sm->meta_info->name) { if (doc->meta_info && doc->meta_info->name && *doc->meta_info->name) {
XML_WRITE_ATTR(writer, GRAPHML_BERLOGA_SCHEMENAME_ATTR, sm->meta_info->name); XML_WRITE_ATTR(writer, GRAPHML_BERLOGA_SCHEMENAME_ATTR, doc->meta_info->name);
} }
/* write graphml keys */ /* write graphml keys */
@@ -2865,7 +2932,7 @@ static int cyberiada_write_sm_yed(CyberiadaSM* sm, xmlTextWriterPtr writer)
return CYBERIADA_NO_ERROR; 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; xmlTextWriterPtr writer;
int res; int res;
@@ -2875,8 +2942,8 @@ int cyberiada_write_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat
return CYBERIADA_BAD_PARAMETER; return CYBERIADA_BAD_PARAMETER;
} }
if (!sm) { if (!doc) {
ERROR("empty SM to write\n"); ERROR("empty SM document to write\n");
return CYBERIADA_BAD_PARAMETER; return CYBERIADA_BAD_PARAMETER;
} }
@@ -2894,9 +2961,14 @@ int cyberiada_write_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat
} }
if (format == cybxmlYED) { 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) { } else if (format == cybxmlCyberiada) {
res = cyberiada_write_sm_cyberiada(sm, writer); res = cyberiada_write_sm_document_cyberiada(doc, writer);
} }
if (res != CYBERIADA_NO_ERROR) { if (res != CYBERIADA_NO_ERROR) {
ERROR("error writing xml %d\n", res); ERROR("error writing xml %d\n", res);

View File

@@ -40,12 +40,8 @@ typedef enum {
cybNodeComment = 8, /* comment node */ cybNodeComment = 8, /* comment node */
cybNodeMachineComment = 16, /* machine-readable comment node */ cybNodeMachineComment = 16, /* machine-readable comment node */
cybNodeInitial = 32, /* initial pseudostate */ cybNodeInitial = 32, /* initial pseudostate */
cybNodeFinal = 64, /* final pseudostate */ cybNodeFinal = 64, /* final state */
cybNodeChoice = 128, /* final pseudostate */ cybNodeChoice = 128, /* choice pseudostate */
cybNodeEntry = 256, /* entry pseudostate */
cybNodeExit = 512, /* exit pseudostate */
cybNodeShallowHistory = 1024, /* shallow history pseudostate */
cybNodeTerminate = 2048, /* terminate pseudostate */
} CyberiadaNodeType; } CyberiadaNodeType;
typedef unsigned int CyberiadaNodeTypeMask; typedef unsigned int CyberiadaNodeTypeMask;
@@ -98,7 +94,7 @@ typedef struct _CyberiadaNode {
size_t id_len; size_t id_len;
char* title; char* title;
size_t title_len; size_t title_len;
CyberiadaAction* action; CyberiadaAction* actions;
CyberiadaRect* geometry_rect; CyberiadaRect* geometry_rect;
struct _CyberiadaNode* next; struct _CyberiadaNode* next;
struct _CyberiadaNode* parent; struct _CyberiadaNode* parent;
@@ -126,48 +122,67 @@ typedef struct _CyberiadaEdge {
struct _CyberiadaEdge* next; struct _CyberiadaEdge* next;
} CyberiadaEdge; } 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) */ /* SM graph (state machine) */
typedef struct { typedef struct _CyberiadaSM {
char* format; /* SM graph format string */
size_t format_len; /* SM graph format string length */
CyberiadaMetainformation* meta_info;
CyberiadaNode* nodes; CyberiadaNode* nodes;
CyberiadaEdge* edges; CyberiadaEdge* edges;
struct _CyberiadaSM* next;
} CyberiadaSM; } 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 */ /* SM GraphML supported formats */
typedef enum { typedef enum {
cybxmlCyberiada = 0, cybxmlCyberiada = 0,
cybxmlYED, cybxmlYED = 1,
cybxmlUnknown cybxmlUnknown = 2
} CyberiadaXMLFormat; } CyberiadaXMLFormat;
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
@@ -188,28 +203,28 @@ typedef enum {
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
/* Allocate the SM structure in memory (for heap usage) */ /* Allocate the SM structure in memory (for heap usage) */
CyberiadaSM* cyberiada_create_sm(void); CyberiadaDocument* cyberiada_create_sm_document(void);
/* Initialize the SM structure */ /* Initialize the SM structure */
/* Do not use the structure before the initialization! */ /* 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 */ /* Cleanup the content of the SM structure */
/* Free the allocated memory of the structure content but not the structure itself */ /* 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) */ /* 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 */ /* Read an XML file and decode the SM structure */
/* Allocate the SM structure first */ /* Allocate the SM document structure first */
int cyberiada_read_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat format); int cyberiada_read_sm_document(CyberiadaDocument* doc, const char* filename, CyberiadaXMLFormat format);
/* Encode the SM structure and write the data to an XML file */ /* Encode the SM document structure and write the data to an XML file */
int cyberiada_write_sm(CyberiadaSM* sm, const char* filename, CyberiadaXMLFormat format); int cyberiada_write_sm_document(CyberiadaDocument* doc, const char* filename, CyberiadaXMLFormat format);
/* Print the SM structure to stdout */ /* Print the SM structure to stdout */
int cyberiada_print_sm(CyberiadaSM* sm); int cyberiada_print_sm_document(CyberiadaDocument* doc);
#ifdef __cplusplus #ifdef __cplusplus
} }

10
test.c
View File

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