libutap  0.93
Uppaal Timed Automata Parser
xmlwriter.cpp
Go to the documentation of this file.
1 // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 
3 /* libutap - Uppaal Timed Automata Parser.
4  Copyright (C) 2002-2006 Uppsala University and Aalborg University.
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public License
8  as published by the Free Software Foundation; either version 2.1 of
9  the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  USA
20  */
21 
22 #include "utap/xmlwriter.h"
23 #include <cstring>
24 
25 using std::vector;
26 using std::list;
27 using std::map;
28 using std::ostringstream;
29 using std::string;
30 using namespace UTAP;
31 using namespace UTAP::Constants;
32 
33 #define MY_ENCODING "utf-8"
34 #define STEP 120
35 #define PINK "#ff6666" //error state color
36 #define PI 3.1416
37 #define RADIUS 80
38 
39 string UTAP::concat(const string& s, int i) {
40  std::ostringstream o;
41  o << s << i;
42  return o.str();
43 }
44 
45 string UTAP::concatDouble(const string& s, double i) {
46  std::ostringstream o;
47  o << s << i;
48  return o.str();
49 }
50 
51 XMLWriter::XMLWriter(xmlTextWriterPtr writer, TimedAutomataSystem* taSystem)
52 : writer(writer), taSystem(taSystem) {
53 }
54 
56  xmlFreeTextWriter(writer);
57 }
58 
59 /* Starts an element named "element" with no content,
60  * as child of the current element or
61  * as root (if it's the first element)*/
62 void XMLWriter::startElement(const char* element) {
63  if (xmlTextWriterStartElement(writer, xmlCharStrdup(element)) < 0) {
64  throw std::runtime_error("Error at xmlTextWriterStartElement");
65  }
66 }
67 
68 /* Closes the current element. */
70  if (xmlTextWriterEndElement(writer) < 0) {
71  throw std::runtime_error("Error at xmlTextWriterEndElement");
72  }
73 }
74 
75 /* Writes an element named "name", with the content
76  * "content" as child of the current element. */
77 void XMLWriter::writeElement(const char* name, const char* content) {
78  if (xmlTextWriterWriteElement(writer, xmlCharStrdup(name),
79  xmlCharStrdup(content)) < 0) {
80  throw std::runtime_error("Error at xmlTextWriterWriteElement");
81  }
82 }
83 
84 /* Writes a String in the current element. */
85 void XMLWriter::writeString(const char* data) {
86  if (xmlTextWriterWriteString(writer, xmlCharStrdup(data)) < 0) {
87  throw std::runtime_error("Error at xmlTextWriterWriteString");
88  }
89 }
90 
91 /* Write a String in the current element. */
92 void XMLWriter::xmlwriteString(const xmlChar* data) {
93  if (xmlTextWriterWriteString(writer, data) < 0) {
94  throw std::runtime_error("Error at xmlTextWriterWriteString");
95  }
96 }
97 
98 /* Adds an attribute with name "name" and value "value"
99  * to the current element. */
100 void XMLWriter::writeAttribute(const char* name, const char* value) {
101  if (xmlTextWriterWriteAttribute(writer, xmlCharStrdup(name),
102  xmlCharStrdup(value)) < 0) {
103  throw std::runtime_error("Error at xmlTextWriterWriteAttribute");
104  }
105 }
106 
109  string globalDeclarations = taSystem->getGlobals().toString(true);
110  globalDeclarations += "\n";
111  globalDeclarations += getChanPriority();
112  globalDeclarations += " ";
113  writeElement("declaration", globalDeclarations.c_str());
114 }
115 
117  const list<chan_priority_t>* chanProc = &(taSystem->getChanPriorities());
118  list<chan_priority_t>::const_iterator itr;
119  string str = "";
120  if (!chanProc->empty()) {
121  str += "// channel priorities\n";
122  for (itr = chanProc->begin(); itr != chanProc->end(); ++itr) {
123  str += itr->toString() + ";";
124  str += "\n";
125  }
126  }
127  return str;
128 }
129 
130 /* writes a "label" element with the "kind", "x" and "y" attributes
131  * an with the "data" content. */
132 void XMLWriter::label(const char* kind, string data, int x, int y) {
133  if (data == "1") {
134  return;
135  }
136  if (data.substr(0, 5) == "1 && ") {
137  data = data.substr(5, data.size() - 5);
138  }
139  xmlChar * tmp = ConvertInput(data.c_str(), MY_ENCODING);
140  if (tmp == NULL) {
141  return;
142  }
143  startElement("label");
144  writeAttribute("kind", kind);
145  writeAttribute("x", concat("", x).c_str());
146  writeAttribute("y", concat("", y).c_str());
147  xmlwriteString(tmp);
148  xmlFree(tmp);
149  endElement();
150 }
151 
152 void XMLWriter::name(const state_t& state, int x, int y) {
153  const char* name = state.uid.getName().c_str();
154  startElement("name");
155  writeAttribute("x", concat("", x).c_str());
156  writeAttribute("y", concat("", y).c_str());
157  writeString(name);
158  endElement();
159 }
160 
161 void XMLWriter::writeStateAttributes(const state_t& state, int x, int y) {
162  int32_t id = state.locNr;
163  writeAttribute("id", concat("id", id).c_str());
164  writeAttribute("x", concat("", x).c_str());
165  writeAttribute("y", concat("", y).c_str());
166 }
167 
168 /* writes a location */
169 void XMLWriter::location(const state_t& state) {
170  startElement("location");
171  int x = STEP * state.locNr;
172  int y = STEP * state.locNr;
173  //identifier, x, y (attributes)
174  writeStateAttributes(state, x, y);
175  if (state.uid.getName() == "Err") {
176  writeAttribute("color", PINK);
177  }
178  // name (element)
179  name(state, x + 8, y + 8);
180  // invariant
181  if (!state.invariant.empty()) {
182  const char* invariant = state.invariant.toString().c_str();
183  label("invariant", invariant, x + 8, y + 24);
184  }
185  // "committed" or "urgent" element
186  if (state.uid.getType().is(COMMITTED)) {
187  startElement("committed");
188  endElement();
189  } else if (state.uid.getType().is(URGENT)) {
190  startElement("urgent");
191  endElement();
192  }
193  endElement(); //end of the "location" element
194 }
195 
196 /* writes the init tag */
197 void XMLWriter::init(const template_t& templ) {
198  int id = static_cast<const state_t*> (templ.init.getData())->locNr;
199  startElement("init");
200  writeAttribute("ref", concat("id", id).c_str());
201  endElement();
202 }
203 
204 /* writes the source of the given edge */
205 int XMLWriter::source(const edge_t& edge) {
206  int loc = edge.src->locNr;
207  const char* id = concat("id", loc).c_str();
208  startElement("source");
209  writeAttribute("ref", id);
210  endElement();
211  return loc;
212 }
213 
214 /* writes the target of the given edge */
215 int XMLWriter::target(const edge_t& edge) {
216  int loc = edge.dst->locNr;
217  const char* id = concat("id", loc).c_str();
218  startElement("target");
219  writeAttribute("ref", id);
220  endElement();
221  return loc;
222 }
223 
224 void XMLWriter::selfLoop(int loc, float initialAngle, const edge_t& edge) { // four loops in PI/2
225  float begin = initialAngle + PI / 8 * selfLoops[loc] + 0.1;
226  float end = begin + PI / 8 - 0.1;
227  int l = loc*STEP;
228  int x1 = l + (int) (RADIUS * cos(begin));
229  int y1 = l + (int) (RADIUS * sin(begin));
230  int x2 = l + (int) (RADIUS * cos(end));
231  int y2 = l + (int) (RADIUS * sin(end));
232  int x3 = l + (int) ((RADIUS + 10) * cos((begin + end) / 2));
233  int y3 = l + (int) ((RADIUS + 10) * sin((begin + end) / 2));
234  selfLoops[loc]++;
235 
236  labels(x3, y3, edge); //TODO
237  nail(x1, y1);
238  nail(x2, y2);
239 }
240 
241 void XMLWriter::nail(int x, int y) {
242  startElement("nail");
243  writeAttribute("x", concat("", x).c_str());
244  writeAttribute("y", concat("", y).c_str());
245  endElement();
246 }
247 
248 /* writes a transition */
249 void XMLWriter::transition(const edge_t& edge) {
250  startElement("transition");
251  // source and target
252  int src = source(edge);
253  int dst = target(edge);
254  if (src == dst) {
255  float angle = (edge.src->uid.getName() != "lpmin") ? 3 * PI / 2 : PI;
256  selfLoop(src, angle, edge);
257  } else {
258  int x = STEP * src;
259  int y = STEP * dst;
260  // labels
261  labels(x, y, edge);
262  nail(x, y);
263  }
264  endElement(); // end of the "transition" element
265 }
266 
267 void XMLWriter::labels(int x, int y, const edge_t& edge) {
268  string str;
269  if (edge.select.getSize() > 0) {
270  str = edge.select[0].getName() + " : ";
271  if (edge.select[0].getType().size() > 0
272  && edge.select[0].getType()[0].size() > 0) {
273  str += edge.select[0].getType()[0].getLabel(0);
274  } //else ? should not happen
275  label("select", str, x, y - 32);
276  }
277  if (!edge.guard.empty()) {
278  label("guard", edge.guard.toString(), x, y - 16);
279  }
280  if (!edge.sync.empty()) {
281  label("synchronisation", edge.sync.toString(), x, y);
282  }
283  if (!edge.assign.empty()) {
284  label("assignment", edge.assign.toString(), x, y + 16);
285  }
286 }
287 
289 void XMLWriter::taTempl(const template_t& templ) {
290  if (!templ.isTA) {
291  return;
292  }
293  selfLoops.clear();
294  string name = templ.uid.getName();
295  string parameters = templ.writeParameters();
296  string declarations = templ.toString(false);
297 
298  startElement("template");
299  writeElement("name", name.c_str());
300  writeElement("parameter", parameters.c_str());
301  writeElement("declaration", declarations.c_str());
302 
303  //locations
304  std::deque<state_t>::const_iterator s_itr;
305  for (s_itr = templ.states.begin(); s_itr != templ.states.end(); ++s_itr) {
306  location(*s_itr);
307  selfLoops.insert(std::pair<int, int>(s_itr->locNr, 0));
308  }
309  // initial location
310  init(templ);
311  //transitions
312  std::deque<edge_t>::const_iterator e_itr;
313  for (e_itr = templ.edges.begin(); e_itr != templ.edges.end(); ++e_itr) {
314  transition(*e_itr);
315  }
316  endElement(); // end of the "template" tag
317 }
318 
319 void XMLWriter::system_instantiation() { // TODO proc priority
320  const std::list<instance_t>* instances = &(taSystem->getProcesses());
321  string str = "";
322  string proc = "";
323  std::list<instance_t>::const_iterator itr;
324  for (itr = instances->begin(); itr != instances->end(); ++itr) {
325  if (itr->uid.getName() != itr->templ->uid.getName()) {
326  str += itr->uid.getName() + " = "
327  + itr->templ->uid.getName() + "("
328  + itr->writeArguments() + ");\n";
329  }
330  proc += itr->uid.getName() + ", ";
331  }
332  proc = proc.substr(0, proc.size() - 2);
333  str += "system " + proc + "; ";
334  writeElement("system", str.c_str());
335 }
336 
339  startDocument();
340  startElement("nta");
341  declaration(); // global declarations
342 
343  const list<template_t>* templates = &(taSystem->getTemplates());
344  std::list<template_t>::const_iterator itr; // = taSystem->getTemplates().begin();
345  for (itr = templates->begin(); itr != templates->end(); ++itr) {
346  taTempl(*itr);
347  }
349  endElement(); // close the "nta" element
350  endDocument();
351 }
352 
354  /* Starts the document with the xml default for the version,
355  * encoding UTF-8 and the default for the standalone
356  * declaration. */
357  if (xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL) < 0) {
358  throw std::runtime_error("Error at xmlTextWriterStartDocument");
359  return;
360  }
361  xmlTextWriterWriteDTD(writer, (xmlChar *) "nta",
362  (xmlChar *) "-//Uppaal Team//DTD Flat System 1.1//EN",
363  (xmlChar *) "http://www.it.uu.se/research/group/darts/uppaal/flat-1_1.dtd", NULL);
364  xmlTextWriterSetIndent(writer, 1);
365  xmlTextWriterSetIndentString(writer, (xmlChar *) " ");
366 }
367 
369  if (xmlTextWriterEndDocument(writer) < 0) {
370  throw std::runtime_error("Error at xmlTextWriterEndDocument");
371  }
372 }
373 
383 xmlChar * UTAP::ConvertInput(const char *in, const char *encoding) {
384  xmlChar *out;
385  int ret;
386  int size;
387  int out_size;
388  int temp;
389  xmlCharEncodingHandlerPtr handler;
390 
391  if (in == 0)
392  return 0;
393 
394  handler = xmlFindCharEncodingHandler(encoding);
395  if (!handler) {
396  printf("ConvertInput: no encoding handler found for '%s'\n",
397  encoding ? encoding : "");
398  return 0;
399  }
400 
401  size = (int) strlen(in) + 1;
402  out_size = size * 2 - 1;
403  out = (unsigned char *) xmlMalloc((size_t) out_size);
404 
405  if (out != 0) {
406  temp = size - 1;
407  ret = handler->input(out, &out_size, (const xmlChar *) in, &temp);
408  if ((ret < 0) || (temp - size + 1)) {
409  if (ret < 0) {
410  printf("ConvertInput: conversion wasn't successful.\n");
411  } else {
412  printf
413  ("ConvertInput: conversion wasn't successful. converted: %i octets.\n",
414  temp);
415  }
416 
417  xmlFree(out);
418  out = 0;
419  } else {
420  out = (unsigned char *) xmlRealloc(out, out_size + 1);
421  out[out_size] = 0; /*null terminating out */
422  }
423  } else {
424  printf("ConvertInput: no mem\n");
425  }
426  return out;
427 }
428 
429 
430 using namespace UTAP;
431 //#if defined(LIBXML_WRITER_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
432 
433 int32_t writeXMLFile(const char *filename, TimedAutomataSystem* taSystem) {
434  xmlTextWriterPtr writer;
435 
436  /* Create a new XmlWriter for filename, with no compression. */
437  writer = xmlNewTextWriterFilename(filename, 0);
438  if (writer == NULL) {
439  throw std::runtime_error("Error creating the xml writer");
440  }
441  XMLWriter(writer, taSystem).project();
442 
443  //xmlFreeTextWriter(writer);
444  return 0;
445 }
XMLWriter(xmlTextWriterPtr writer, TimedAutomataSystem *taSystem)
Definition: xmlwriter.cpp:51
std::map< int, int > selfLoops
Definition: xmlwriter.h:59
symbol_t uid
The symbol of the location.
Definition: system.h:58
bool empty() const
Returns true if this is an empty expression.
Definition: expression.cpp:671
void project()
Parse the project document.
Definition: xmlwriter.cpp:338
std::deque< state_t > states
Locations.
Definition: system.h:358
uint32_t getSize() const
Returns the number of symbols in this frame.
Definition: symbols.cpp:328
void system_instantiation()
Definition: xmlwriter.cpp:319
void labels(int x, int y, const edge_t &edge)
Definition: xmlwriter.cpp:267
Information about a location.
Definition: system.h:56
void taTempl(const template_t &templ)
writes a template
Definition: xmlwriter.cpp:289
expression_t guard
The guard.
Definition: system.h:95
std::string writeParameters() const
Definition: system.cpp:250
void writeStateAttributes(const state_t &state, int x, int y)
Definition: xmlwriter.cpp:161
std::string getName() const
Returns the name (identifier) of this symbol.
Definition: symbols.cpp:228
expression_t sync
The synchronisation.
Definition: system.h:97
void label(const char *kind, std::string data, int x, int y)
Definition: xmlwriter.cpp:132
int32_t locNr
Location number in template.
Definition: system.h:62
xmlTextWriterPtr writer
The underlying xmlTextWriter.
Definition: xmlwriter.h:57
state_t * src
Pointer to source location.
Definition: system.h:90
std::string getChanPriority() const
Definition: xmlwriter.cpp:116
Information about an edge.
Definition: system.h:85
void writeString(const char *content)
Definition: xmlwriter.cpp:85
void declaration()
Parses optional declaration.
Definition: xmlwriter.cpp:108
expression_t assign
The assignment.
Definition: system.h:96
void startDocument()
Definition: xmlwriter.cpp:353
void selfLoop(int loc, float initialAngle, const edge_t &edge)
Definition: xmlwriter.cpp:224
state_t * dst
Pointer to destination location.
Definition: system.h:92
std::list< instance_t > & getProcesses()
Returns the processes of the system.
Definition: system.cpp:956
int target(const edge_t &edge)
Definition: xmlwriter.cpp:215
void name(const state_t &state, int x, int y)
Definition: xmlwriter.cpp:152
std::deque< edge_t > edges
Edges.
Definition: system.h:360
expression_t invariant
The invariant.
Definition: system.h:59
void nail(int x, int y)
Definition: xmlwriter.cpp:241
#define MY_ENCODING
Definition: xmlwriter.cpp:33
#define PI
Definition: xmlwriter.cpp:36
#define PINK
Definition: xmlwriter.cpp:35
std::string toString(bool old=false) const
Returns a string representation of the expression.
void writeElement(const char *name, const char *content)
Definition: xmlwriter.cpp:77
void endDocument()
Definition: xmlwriter.cpp:368
void startElement(const char *element)
Definition: xmlwriter.cpp:62
xmlChar * ConvertInput(const char *in, const char *encoding)
ConvertInput: : string in a given encoding : the encoding used.
Definition: xmlwriter.cpp:383
std::string concat(const std::string &s, int i)
concatenates a string and an int
type_t getType() const
Returns the type of this symbol.
Definition: symbols.cpp:205
std::string concatDouble(const std::string &s, double i)
concatenates a string and a double
void transition(const edge_t &edge)
Definition: xmlwriter.cpp:249
frame_t select
Frame for non-deterministic select.
Definition: system.h:94
TimedAutomataSystem * taSystem
The system to write.
Definition: xmlwriter.h:58
void endElement()
Definition: xmlwriter.cpp:69
void * getData()
Returns the user data of this symbol.
Definition: symbols.cpp:216
symbol_t init
The initial location.
Definition: system.h:356
std::string toString(bool global=false) const
The following methods are used to write the declarations in an XML file.
Definition: system.cpp:139
void location(const state_t &state)
Definition: xmlwriter.cpp:169
bool is(Constants::kind_t kind) const
Returns true if the type has kind kind or if type is a prefix, RANGE or REF type and the getChild()...
Definition: type.cpp:176
std::list< template_t > & getTemplates()
Returns the templates of the system.
Definition: system.cpp:951
#define RADIUS
Definition: xmlwriter.cpp:37
Definition: lexer.cc:817
int32_t writeXMLFile(const char *filename, TimedAutomataSystem *taSystem)
Definition: xmlwriter.cpp:433
int source(const edge_t &edge)
Definition: xmlwriter.cpp:205
void xmlwriteString(const xmlChar *content)
Definition: xmlwriter.cpp:92
const std::list< chan_priority_t > & getChanPriorities() const
Definition: system.cpp:1335
declarations_t & getGlobals()
Returns the global declarations of the system.
Definition: system.cpp:961
void writeAttribute(const char *name, const char *value)
Definition: xmlwriter.cpp:100
virtual ~XMLWriter()
Definition: xmlwriter.cpp:55
void init(const template_t &templ)
Definition: xmlwriter.cpp:197
#define STEP
Definition: xmlwriter.cpp:34
symbol_t uid
The name.
Definition: system.h:331