OSDN Git Service

cleanup
[openpts/openpts.git] / src / uml.c
1 /*
2  * This file is part of the OpenPTS project.
3  *
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.
8  *
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)
12  * any later version.
13  *
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.
18  *
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.
22  */
23
24 /**
25  * \file src/uml.c
26  * \brief UML2 State Diagram
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2010-04-01
29  * cleanup 2012-01-05 SM
30  *
31  * UML State Diagram (XMI2.1, Eclipse MDT) -> DOT (Graphviz) Utility
32  */
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37
38 #include <libxml/encoding.h>
39 #include <libxml/xmlwriter.h>
40 #include <libxml/parser.h>
41
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>
47 #include <tss/tspi.h>
48
49 #include <openpts.h>
50
51 /*
52 UML
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)"/>
55       </subvertex>
56
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>
62           </specification>
63         </ownedRule>
64       </transition>
65
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)"/>
68       </subvertex>
69
70 DOT
71
72   State  Condition  NextState
73      S0    A=N         S2
74      S0    A=E         S3
75      S0    else        S0
76
77  */
78
79
80 /**
81  * startDocument of SAX parser
82  */
83 void uml2sax_startDocument(void * fctx) {
84     OPENPTS_FSM_CONTEXT *ctx;
85
86     DEBUG_CAL("startDocument - start\n");
87
88     /* check */
89     if (fctx == NULL) {
90         LOG(LOG_ERR, "null input");
91         return;
92     }
93     ctx = (OPENPTS_FSM_CONTEXT *)fctx;
94     ctx->error = 0;
95
96     resetFsmSubvertex(ctx);
97     resetFsmTransition(ctx);
98
99     DEBUG_CAL("startDocument - done\n");
100 }
101
102 /**
103  * endDocument of SAX parser
104  */
105 void uml2sax_endDocument(void * fctx) {
106     OPENPTS_FSM_CONTEXT *ctx;
107
108     /* check */
109     if (fctx == NULL) {
110         LOG(LOG_ERR, "null input");
111         return;
112     }
113     ctx = (OPENPTS_FSM_CONTEXT *)fctx;
114
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");
120     }
121
122     DEBUG_CAL("endDocument - done\n");
123 }
124
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 */
134
135 /**
136  * startElement of SAX parser
137  */
138 void uml2sax_startElement(void* fctx, const xmlChar* name,
139                              const xmlChar** atts) {
140     OPENPTS_FSM_CONTEXT *ctx;
141     int i;
142     char *type;
143     char *value;
144
145     /* check */
146     if (fctx == NULL) {
147         LOG(LOG_ERR, "null input");
148         return;
149     }
150     ctx = (OPENPTS_FSM_CONTEXT *)fctx;
151     if (name == NULL) {
152         LOG(LOG_ERR, "null input");
153         return;
154     }
155
156     // DEBUG_SAX("startElement - \n");
157
158     /* subvertex  */
159     if (!strcmp((char *)name, "subvertex")) {
160         ctx->state = UML2SAX_SUBVERTEX;
161
162         // some state does not have name
163         memset(subvertexName, 0, FSM_BUF_SIZE);
164
165         /* get xmi:id and name attribute ( */
166         if (atts != NULL) {
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),
173                                  "%s", value);
174                     }
175                     if (!strcmp(type, "xmi:id")) {
176                         snprintf(subvertexXmiId, sizeof(subvertexXmiId),
177                                  "%s", value);
178                     }
179                     if (!strcmp(type, "name")) {
180                         snprintf(subvertexName, sizeof(subvertexName),
181                                  "%s", value);
182                     }
183                 }
184             }
185         }
186         // addFsmSubvertex(ctx,subvertexXmiId,subvertexName);
187         memset(doActivityName, 0, FSM_BUF_SIZE);
188
189     } else if (!strcmp((char *)name, "transition")) {
190         ctx->state = UML2SAX_TRANSITION;
191         memset(charbuf, 0, FSM_BUF_SIZE);  // clear
192
193         /* get source and target attribute ( */
194         if (atts != NULL) {
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);
201                     }
202                     if (!strcmp(type, "target")) {
203                         snprintf(targetXmiId, sizeof(targetXmiId), "%s", value);
204                     }
205                 }
206             }
207         }
208     } else if ((!strcmp((char *)name, "doActivity")) &&
209                (ctx->state == UML2SAX_SUBVERTEX)) {
210         ctx->state = UML2SAX_DOACTIVITY;
211
212         /* get name attribute */
213         if (atts != NULL) {
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),
220                                  "%s", value);
221                     }
222                 }
223             }
224         }
225         DEBUG_SAX("doActivity %s\n", doActivityName);
226
227     } else if ((!strcmp((char *)name, "body")) &&
228                (ctx->state == UML2SAX_TRANSITION)) {
229         ctx->state = UML2SAX_BODY;
230     } else if (!strcmp((char *)name, "name")) {
231         //
232     } else if (!strcmp((char *)name, "ownedRule")) {
233         //
234     } else if (!strcmp((char *)name, "specification")) {
235         //
236     } else if (!strcmp((char *)name, "body")) {
237         //
238     } else if (!strcmp((char *)name, "ownedComment")) {
239         //
240     } else if (!strcmp((char *)name, "region")) {
241         //
242     } else if (!strcmp((char *)name, "uml:Model")) {
243         //
244     } else if (!strcmp((char *)name, "packagedElement")) {
245         //
246     } else {
247         DEBUG_SAX("START ELEMENT [%s]\n", name);
248         // ctx->state=0;
249     }
250 }
251
252
253
254 /**
255  * endElement of SAX parser
256  */
257 void uml2sax_endElement(void * fctx, const xmlChar * name) {
258     OPENPTS_FSM_CONTEXT *ctx;
259
260     /* check */
261     if (fctx == NULL) {
262         LOG(LOG_ERR, "null input");
263         return;
264     }
265     ctx = (OPENPTS_FSM_CONTEXT *)fctx;
266     if (name == NULL) {
267         LOG(LOG_ERR, "null input");
268         return;
269     }
270
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);
275     } else {
276         // DEBUG_SAX("END ELEMENT [%s] ",name);
277     }
278 }
279
280 /**
281  * characters of SAX parser
282  *
283  * 20100928 
284  *  Eclipse MDT  ">" =>  &lt;, but  stoped at &lt;   
285  *  LinbML &amp;lt;
286  * 20111228
287  *  <body>eventtype==0x0d,digest==base64!,digest_count&gt;=iml.ipl.count</body>
288  *  [44] eventtype==0x0d,digest==base64!,digest_count
289  *  Libxml stop at "&gt;" :-(
290  *    libxml2-2.7.6-1.el6.x86_64
291  *  Use text notation (gt/ge/lt/le) instead of <,>
292  */
293 void  uml2sax_characters(void* fctx, const xmlChar * ch, int len) {
294     OPENPTS_FSM_CONTEXT *ctx;
295     char buf[FSM_BUF_SIZE];
296
297     /* check */
298     if (fctx == NULL) {
299         LOG(LOG_ERR, "null input");
300         return;
301     }
302     ctx = (OPENPTS_FSM_CONTEXT *)fctx;
303     if ((len > 0) && (ch == NULL)) {
304         LOG(LOG_ERR, "null input");
305         return;
306     }
307
308     if (len < FSM_BUF_SIZE) {
309         memcpy(buf, ch, len);
310         buf[len]= 0;
311     } else {
312         memcpy(buf, ch, sizeof(buf));
313         buf[FSM_BUF_SIZE-1]= 0;
314     }
315
316     switch (ctx->state) {
317     case UML2SAX_SUBVERTEX:
318         break;
319     case UML2SAX_BODY:
320         memcpy(charbuf, buf, FSM_BUF_SIZE);
321         ctx->state = 0;
322         break;
323     default:
324         // DEBUG_SAX("characters[%d]=[%s]\n", len, buf);
325         break;
326     }
327 }
328
329 /**
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
333  */
334 int readUmlModel(OPENPTS_FSM_CONTEXT * ctx, char *umlfile) {
335     xmlSAXHandler  sax_handler;
336     int rc;
337
338     /* check */
339     if (ctx == NULL) {
340         LOG(LOG_ERR, "null input");
341         return PTS_FATAL;
342     }
343     if (umlfile == NULL) {
344         LOG(LOG_ERR, "null input");
345         return PTS_FATAL;
346     }
347
348     memset(&sax_handler, 0, sizeof(xmlSAXHandler));
349
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;
355
356     /* read UML  */
357
358     DEBUG_CAL("readUmlModel - start\n");
359     DEBUG("Read UML State Diagram      : %s\n", umlfile);
360
361     // http://xmlsoft.org/html/libxml-parser.html#xmlSAXUserParseFile
362     if ((rc = xmlSAXUserParseFile(&sax_handler, (void*)ctx, umlfile)) != 0) {
363         // SAX parse error
364         // free_ret_val(ctx->state.return_val);
365         return rc;
366     } else {
367         /* delete previos one if exist */
368         /* copy */
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
372     }
373 }
374