2 * This file is part of the OpenPTS project.
4 * The Initial Developer of the Original Code is International
5 * Business Machines Corporation. Portions created by IBM
6 * Corporation are Copyright (C) 2010 International Business
7 * Machines Corporation. All Rights Reserved.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the Common Public License as published by
11 * IBM Corporation; either version 1 of the License, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * Common Public License for more details.
19 * You should have received a copy of the Common Public License
20 * along with this program; if not, a copy can be viewed at
21 * http://www.opensource.org/licenses/cpl1.0.php.
26 * \brief UML2 State Diagram
27 * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
29 * cleanup 2012-01-05 SM
31 * UML State Diagram (XMI2.1, Eclipse MDT) -> DOT (Graphviz) Utility
38 #include <libxml/encoding.h>
39 #include <libxml/xmlwriter.h>
40 #include <libxml/parser.h>
42 #include <tss/platform.h>
43 #include <tss/tss_defines.h>
44 #include <tss/tss_typedef.h>
45 #include <tss/tss_structs.h>
46 #include <tss/tss_error.h>
53 <subvertex xmi:type="uml:State" xmi:id="Kk02PKa3" name="CRTM_START" visibility="public">
54 <doActivity xmi:type="uml:Activity" xmi:id="_OzCawRyrEd6jytZ7WXwL3w" name="resetPCR(0)"/>
57 <transition xmi:id="Kmls2mS0" visibility="public" kind="local" source="EV_POST_CODE" target="KmlrdRO3" guard="_OzMy0RyrEd6jytZ7WXwL3w">
58 <name xsi:nil="true"/>
59 <ownedRule xmi:id="_OzMy0RyrEd6jytZ7WXwL3w" name="">
60 <specification xmi:type="uml:OpaqueExpression" xmi:id="_OzMy0hyrEd6jytZ7WXwL3w" name="">
61 <body>eventtype == 0x0A</body>
66 <subvertex xmi:type="uml:State" xmi:id="KoBy4Id1" name="BIOS_PCR0_Verified" visibility="public">
67 <doActivity xmi:type="uml:Activity" xmi:id="_OzCawByrEd6jytZ7WXwL3w" name="setAssertion(bios.pcr0.integrity, valid)"/>
72 State Condition NextState
81 * startDocument of SAX parser
83 void uml2sax_startDocument(void * fctx) {
84 OPENPTS_FSM_CONTEXT *ctx;
86 DEBUG_CAL("startDocument - start\n");
90 LOG(LOG_ERR, "null input");
93 ctx = (OPENPTS_FSM_CONTEXT *)fctx;
96 resetFsmSubvertex(ctx);
97 resetFsmTransition(ctx);
99 DEBUG_CAL("startDocument - done\n");
103 * endDocument of SAX parser
105 void uml2sax_endDocument(void * fctx) {
106 OPENPTS_FSM_CONTEXT *ctx;
110 LOG(LOG_ERR, "null input");
113 ctx = (OPENPTS_FSM_CONTEXT *)fctx;
115 /* set start state */
116 // TODO(munetoh) ID must be "Start"
117 ctx->curr_state = getSubvertex(ctx, "Start");
118 if (ctx->curr_state == NULL) {
119 LOG(LOG_ERR, "Start state is missing\n");
122 DEBUG_CAL("endDocument - done\n");
125 // TODO(munetoh) move to cxt
126 // it can use RM_CTX. 20100617 SM
127 char sourceXmiId[FSM_BUF_SIZE]; /**< move to ctx */
128 char targetXmiId[FSM_BUF_SIZE]; /**< move to ctx */
129 char subvertexXmiType[FSM_BUF_SIZE]; /**< move to ctx */
130 char subvertexXmiId[FSM_BUF_SIZE]; /**< move to ctx */
131 char subvertexName[FSM_BUF_SIZE]; /**< move to ctx */
132 char charbuf[FSM_BUF_SIZE]; /**< move to ctx */
133 char doActivityName[FSM_BUF_SIZE]; /**< move to ctx */
136 * startElement of SAX parser
138 void uml2sax_startElement(void* fctx, const xmlChar* name,
139 const xmlChar** atts) {
140 OPENPTS_FSM_CONTEXT *ctx;
147 LOG(LOG_ERR, "null input");
150 ctx = (OPENPTS_FSM_CONTEXT *)fctx;
152 LOG(LOG_ERR, "null input");
156 // DEBUG_SAX("startElement - \n");
159 if (!strcmp((char *)name, "subvertex")) {
160 ctx->state = UML2SAX_SUBVERTEX;
162 // some state does not have name
163 memset(subvertexName, 0, FSM_BUF_SIZE);
165 /* get xmi:id and name attribute ( */
167 for (i = 0; (atts[i] != NULL); i++) {
168 type = (char *)atts[i++];
169 if (atts[i] != NULL) {
170 value= (char *)atts[i];
171 if (!strcmp(type, "xmi:type")) {
172 snprintf(subvertexXmiType, sizeof(subvertexXmiType),
175 if (!strcmp(type, "xmi:id")) {
176 snprintf(subvertexXmiId, sizeof(subvertexXmiId),
179 if (!strcmp(type, "name")) {
180 snprintf(subvertexName, sizeof(subvertexName),
186 // addFsmSubvertex(ctx,subvertexXmiId,subvertexName);
187 memset(doActivityName, 0, FSM_BUF_SIZE);
189 } else if (!strcmp((char *)name, "transition")) {
190 ctx->state = UML2SAX_TRANSITION;
191 memset(charbuf, 0, FSM_BUF_SIZE); // clear
193 /* get source and target attribute ( */
195 for (i = 0; (atts[i] != NULL); i++) {
196 type = (char *)atts[i++];
197 if (atts[i] != NULL) {
198 value= (char *)atts[i];
199 if (!strcmp(type, "source")) {
200 snprintf(sourceXmiId, sizeof(sourceXmiId), "%s", value);
202 if (!strcmp(type, "target")) {
203 snprintf(targetXmiId, sizeof(targetXmiId), "%s", value);
208 } else if ((!strcmp((char *)name, "doActivity")) &&
209 (ctx->state == UML2SAX_SUBVERTEX)) {
210 ctx->state = UML2SAX_DOACTIVITY;
212 /* get name attribute */
214 for (i = 0; (atts[i] != NULL); i++) {
215 type = (char *)atts[i++];
216 if (atts[i] != NULL) {
217 value= (char *)atts[i];
218 if (!strcmp(type, "name")) {
219 snprintf(doActivityName, sizeof(doActivityName),
225 DEBUG_SAX("doActivity %s\n", doActivityName);
227 } else if ((!strcmp((char *)name, "body")) &&
228 (ctx->state == UML2SAX_TRANSITION)) {
229 ctx->state = UML2SAX_BODY;
230 } else if (!strcmp((char *)name, "name")) {
232 } else if (!strcmp((char *)name, "ownedRule")) {
234 } else if (!strcmp((char *)name, "specification")) {
236 } else if (!strcmp((char *)name, "body")) {
238 } else if (!strcmp((char *)name, "ownedComment")) {
240 } else if (!strcmp((char *)name, "region")) {
242 } else if (!strcmp((char *)name, "uml:Model")) {
244 } else if (!strcmp((char *)name, "packagedElement")) {
247 DEBUG_SAX("START ELEMENT [%s]\n", name);
255 * endElement of SAX parser
257 void uml2sax_endElement(void * fctx, const xmlChar * name) {
258 OPENPTS_FSM_CONTEXT *ctx;
262 LOG(LOG_ERR, "null input");
265 ctx = (OPENPTS_FSM_CONTEXT *)fctx;
267 LOG(LOG_ERR, "null input");
271 if (!strcmp((char *)name, "subvertex")) {
272 addFsmSubvertex(ctx, subvertexXmiType, subvertexXmiId, subvertexName, doActivityName);
273 } else if (!strcmp((char *)name, "transition")) {
274 addFsmTransition(ctx, sourceXmiId, targetXmiId, charbuf);
276 // DEBUG_SAX("END ELEMENT [%s] ",name);
281 * characters of SAX parser
284 * Eclipse MDT ">" => <, but stoped at <
287 * <body>eventtype==0x0d,digest==base64!,digest_count>=iml.ipl.count</body>
288 * [44] eventtype==0x0d,digest==base64!,digest_count
289 * Libxml stop at ">" :-(
290 * libxml2-2.7.6-1.el6.x86_64
291 * Use text notation (gt/ge/lt/le) instead of <,>
293 void uml2sax_characters(void* fctx, const xmlChar * ch, int len) {
294 OPENPTS_FSM_CONTEXT *ctx;
295 char buf[FSM_BUF_SIZE];
299 LOG(LOG_ERR, "null input");
302 ctx = (OPENPTS_FSM_CONTEXT *)fctx;
303 if ((len > 0) && (ch == NULL)) {
304 LOG(LOG_ERR, "null input");
308 if (len < FSM_BUF_SIZE) {
309 memcpy(buf, ch, len);
312 memcpy(buf, ch, sizeof(buf));
313 buf[FSM_BUF_SIZE-1]= 0;
316 switch (ctx->state) {
317 case UML2SAX_SUBVERTEX:
320 memcpy(charbuf, buf, FSM_BUF_SIZE);
324 // DEBUG_SAX("characters[%d]=[%s]\n", len, buf);
330 * read UML2 State Diagram file (using SAX parser)
331 * @param ctx FSM_CONTEXT to store the FSM
332 * @param umlfile UML2 State Diagram file
334 int readUmlModel(OPENPTS_FSM_CONTEXT * ctx, char *umlfile) {
335 xmlSAXHandler sax_handler;
340 LOG(LOG_ERR, "null input");
343 if (umlfile == NULL) {
344 LOG(LOG_ERR, "null input");
348 memset(&sax_handler, 0, sizeof(xmlSAXHandler));
350 sax_handler.startDocument = uml2sax_startDocument;
351 sax_handler.endDocument = uml2sax_endDocument;
352 sax_handler.startElement = uml2sax_startElement;
353 sax_handler.endElement = uml2sax_endElement;
354 sax_handler.characters = uml2sax_characters;
358 DEBUG_CAL("readUmlModel - start\n");
359 DEBUG("Read UML State Diagram : %s\n", umlfile);
361 // http://xmlsoft.org/html/libxml-parser.html#xmlSAXUserParseFile
362 if ((rc = xmlSAXUserParseFile(&sax_handler, (void*)ctx, umlfile)) != 0) {
364 // free_ret_val(ctx->state.return_val);
367 /* delete previos one if exist */
369 ctx->uml_file = smalloc_assert(umlfile);
370 DEBUG_CAL("readUmlModel - done\n");
371 return ctx->error; // Success (0) or ERROR of IR if exist