summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2015-01-19 16:41:18 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2015-01-19 16:41:18 (GMT)
commitff86d690dc02d7dd495000331d378e7d8eb688ac (patch)
tree5214786f7e575952d3cba0919e5071f3a783050b /apps
parent42437db418574f2a80d098e568b9498a21343800 (diff)
downloaduscxml-ff86d690dc02d7dd495000331d378e7d8eb688ac.zip
uscxml-ff86d690dc02d7dd495000331d378e7d8eb688ac.tar.gz
uscxml-ff86d690dc02d7dd495000331d378e7d8eb688ac.tar.bz2
Plenty of smaller fixes and adaptations
Diffstat (limited to 'apps')
-rw-r--r--apps/uscxml-analyze.cpp193
-rw-r--r--apps/uscxml-browser.cpp36
-rw-r--r--apps/uscxml-transform.cpp119
3 files changed, 291 insertions, 57 deletions
diff --git a/apps/uscxml-analyze.cpp b/apps/uscxml-analyze.cpp
new file mode 100644
index 0000000..75ec48c
--- /dev/null
+++ b/apps/uscxml-analyze.cpp
@@ -0,0 +1,193 @@
+#include "uscxml/config.h"
+#include "uscxml/Interpreter.h"
+#include "uscxml/transform/ChartToFSM.h"
+#include "uscxml/DOMUtils.h"
+#include <glog/logging.h>
+#include <fstream>
+#include <iostream>
+
+#include "uscxml/Factory.h"
+#include "uscxml/server/HTTPServer.h"
+#include "getopt.h"
+
+#ifdef HAS_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef HAS_EXECINFO_H
+#include <execinfo.h>
+#endif
+
+#ifdef HAS_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#define ANNOTATE(envKey, annotationParam) \
+envVarIsTrue(envKey) || std::find(annotations.begin(), annotations.end(), annotationParam) != annotations.end()
+
+void printUsageAndExit(const char* progName) {
+ // remove path from program name
+ std::string progStr(progName);
+ if (progStr.find_last_of(PATH_SEPERATOR) != std::string::npos) {
+ progStr = progStr.substr(progStr.find_last_of(PATH_SEPERATOR) + 1, progStr.length() - (progStr.find_last_of(PATH_SEPERATOR) + 1));
+ }
+
+ printf("%s version " USCXML_VERSION " (" CMAKE_BUILD_TYPE " build - " CMAKE_COMPILER_STRING ")\n", progStr.c_str());
+ printf("Usage\n");
+ printf("\t%s", progStr.c_str());
+#ifdef BUILD_AS_PLUGINS
+ printf(" [-p pluginPath]");
+#endif
+ printf(" [URL]");
+ printf("\n");
+ exit(1);
+}
+
+int main(int argc, char** argv) {
+ using namespace uscxml;
+
+ std::string outType;
+ std::string pluginPath;
+ std::string inputFile;
+ std::string outputFile;
+ std::list<std::string> annotations;
+
+#if defined(HAS_SIGNAL_H) && !defined(WIN32)
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ // setup logging
+ google::LogToStderr();
+ google::InitGoogleLogging(argv[0]);
+
+ optind = 0;
+ opterr = 0;
+
+ struct option longOptions[] = {
+ {"help", required_argument, 0, 'p'},
+ {"plugin-path", required_argument, 0, 'p'},
+ {"loglevel", required_argument, 0, 'l'},
+ {0, 0, 0, 0}
+ };
+
+ // parse global options
+ int optionInd = 0;
+ int option;
+ for (;;) {
+ option = getopt_long_only(argc, argv, "p:l:h", longOptions, &optionInd);
+ if (option == -1) {
+ break;
+ }
+ switch(option) {
+ // cases without short option
+ case 0: {
+ break;
+ }
+ // cases with short-hand options
+ case 'p':
+ pluginPath = optarg;
+ break;
+ case 'l':
+ break;
+ case 'h':
+ case '?': {
+ printUsageAndExit(argv[0]);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ inputFile = argv[optind];
+ }
+
+ // register plugins
+ if (pluginPath.length() > 0) {
+ Factory::setDefaultPluginPath(pluginPath);
+ }
+
+ // start HTTP server
+ HTTPServer::getInstance(31444, 31445, NULL);
+
+ Interpreter interpreter;
+ try {
+ if (inputFile.size() == 0 || inputFile == "-") {
+ LOG(INFO) << "Reading SCXML from STDIN";
+ std::stringstream ss;
+ std::string line;
+ while (std::getline(std::cin, line)) {
+ ss << line;
+ }
+ URL tmp("anonymous.scxml");
+ tmp.toAbsoluteCwd();
+ interpreter = Interpreter::fromXML(ss.str(), tmp);
+ } else {
+ interpreter = Interpreter::fromURL(inputFile);
+ }
+ if (!interpreter) {
+ LOG(ERROR) << "Cannot create interpreter from " << inputFile;
+ exit(EXIT_FAILURE);
+ }
+
+ // analyze here
+ Arabica::XPath::NodeSet<std::string> states = interpreter.getNodeSetForXPath("//" + interpreter.getNameSpaceInfo().xpathPrefix + "state");
+ Arabica::XPath::NodeSet<std::string> final = interpreter.getNodeSetForXPath("//" + interpreter.getNameSpaceInfo().xpathPrefix + "final");
+ Arabica::XPath::NodeSet<std::string> parallels = interpreter.getNodeSetForXPath("//" + interpreter.getNameSpaceInfo().xpathPrefix + "parallel");
+ Arabica::XPath::NodeSet<std::string> shallowHistories = interpreter.getNodeSetForXPath("//" + interpreter.getNameSpaceInfo().xpathPrefix + "history[@type='shallow']");
+ shallowHistories.push_back(interpreter.getNodeSetForXPath("//" + interpreter.getNameSpaceInfo().xpathPrefix + "history[not(@type)]"));
+ Arabica::XPath::NodeSet<std::string> deepHistories = interpreter.getNodeSetForXPath("//" + interpreter.getNameSpaceInfo().xpathPrefix + "history[@type='deep']");
+ Arabica::XPath::NodeSet<std::string> transitions = interpreter.getNodeSetForXPath("//" + interpreter.getNameSpaceInfo().xpathPrefix + "transition");
+
+ std::cout << "# Number of elements" << std::endl;
+ std::cout << "nr_states: " << (states.size() + final.size() + parallels.size()) << std::endl;
+ std::cout << "nr_parallel: " << parallels.size() << std::endl;
+ std::cout << "nr_hist_flat: " << shallowHistories.size() << std::endl;
+ std::cout << "nr_hist_deep: " << deepHistories.size() << std::endl;
+ std::cout << "nr_trans: " << transitions.size() << std::endl;
+
+
+ std::cout << "# Transition Histogram: number of transitions, number of active configurations" << std::endl;
+
+ size_t numberOfLegalConfs = 0;
+ size_t lastBin = 0;
+ std::map<size_t, size_t> histogram = Complexity::getTransitionHistogramm(interpreter.getDocument().getDocumentElement());
+ for (std::map<size_t, size_t>::iterator binIter = histogram.begin(); binIter != histogram.end(); binIter++) {
+ while (binIter->first > lastBin) {
+ std::cout << "th: " << toStr(lastBin++) << ", 0" << std::endl;
+ }
+ std::cout << "th: " << toStr(binIter->first) << ", " << binIter->second << std::endl;
+ numberOfLegalConfs += binIter->second;
+ lastBin = binIter->first + 1;
+ }
+
+ std::stringstream transPowerSetSS;
+ std::string transPowerSetSeperator = "";
+ for (std::map<size_t, size_t>::reverse_iterator binIter = histogram.rbegin(); binIter != histogram.rend(); binIter++) {
+ transPowerSetSS << transPowerSetSeperator << binIter->second << " * " << "2**" << binIter->first;
+ transPowerSetSeperator = " + ";
+ }
+ std::cout << "# Sum of Powersets:" << std::endl;
+ std::cout << "ps_sum: " << transPowerSetSS.str() << std::endl;
+ std::cout << "# Upper bounds:" << std::endl;
+ std::cout << "# \tActive configurations: " << std::endl;
+ std::cout << "up_ac: " << numberOfLegalConfs << std::endl;
+ std::cout << "# \tGlobal configurations: " << std::endl;
+ std::cout << "up_gc: " << Complexity::stateMachineComplexity(interpreter.getDocument().getDocumentElement()) << std::endl;
+
+ std::cout << "# \tGlobal configurations (no history): " << std::endl;
+ std::cout << "up_gcnh: " << Complexity::stateMachineComplexity(interpreter.getDocument().getDocumentElement(), uscxml::Complexity::IGNORE_HISTORY) << std::endl;
+
+ std::cout << "# \tGlobal configurations (no nested data): " << std::endl;
+ std::cout << "up_gcnd: " << Complexity::stateMachineComplexity(interpreter.getDocument().getDocumentElement(), uscxml::Complexity::IGNORE_NESTED_DATA) << std::endl;
+
+ std::cout << "# \tGlobal configurations (no nested data, no history): " << std::endl;
+ std::cout << "up_gcnhd: " << Complexity::stateMachineComplexity(interpreter.getDocument().getDocumentElement(), uscxml::Complexity::IGNORE_HISTORY_AND_NESTED_DATA) << std::endl;
+
+ } catch (Event e) {
+ std::cout << e << std::endl;
+ }
+
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/apps/uscxml-browser.cpp b/apps/uscxml-browser.cpp
index 87b1b1d..0562ba7 100644
--- a/apps/uscxml-browser.cpp
+++ b/apps/uscxml-browser.cpp
@@ -22,40 +22,6 @@
#include <dlfcn.h>
#endif
-class VerboseMonitor : public uscxml::InterpreterMonitor {
- void onStableConfiguration(uscxml::Interpreter interpreter) {
- printConfig(interpreter.getConfiguration());
- }
-
- void beforeProcessingEvent(uscxml::Interpreter interpreter, const uscxml::Event& event) {
- switch (event.eventType) {
- case uscxml::Event::INTERNAL:
- std::cout << "Internal Event: " << event.name << std::endl;
- break;
- case uscxml::Event::EXTERNAL:
- std::cout << "External Event: " << event.name << std::endl;
- break;
- case uscxml::Event::PLATFORM:
- std::cout << "Platform Event: " << event.name << std::endl;
- break;
- }
- }
-
- void beforeCompletion(uscxml::Interpreter interpreter) {
- printConfig(interpreter.getConfiguration());
- }
-
- void printConfig(const Arabica::XPath::NodeSet<std::string>& config) {
- std::string seperator;
- std::cout << "Config: {";
- for (int i = 0; i < config.size(); i++) {
- std::cout << seperator << ATTR_CAST(config[i], "id");
- seperator = ", ";
- }
- std::cout << "}" << std::endl;
- }
-};
-
#ifdef CMAKE_BUILD_TYPE_DEBUG
#ifdef HAS_EXECINFO_H
@@ -206,7 +172,7 @@ int main(int argc, char** argv) {
interpreter.setCapabilities(options.getCapabilities());
if (options.verbose) {
- VerboseMonitor* vm = new VerboseMonitor();
+ StateTransitionMonitor* vm = new StateTransitionMonitor();
interpreter.addMonitor(vm);
}
diff --git a/apps/uscxml-transform.cpp b/apps/uscxml-transform.cpp
index d8a9013..055c1ae 100644
--- a/apps/uscxml-transform.cpp
+++ b/apps/uscxml-transform.cpp
@@ -1,6 +1,7 @@
#include "uscxml/config.h"
#include "uscxml/Interpreter.h"
#include "uscxml/transform/ChartToFlatSCXML.h"
+#include "uscxml/transform/ChartToTex.h"
#include "uscxml/transform/ChartToMinimalSCXML.h"
#include "uscxml/transform/ChartToPromela.h"
#include "uscxml/DOMUtils.h"
@@ -24,6 +25,9 @@
#include <dlfcn.h>
#endif
+#define ANNOTATE(envKey, annotationParam) \
+envVarIsTrue(envKey) || std::find(annotations.begin(), annotations.end(), annotationParam) != annotations.end()
+
class VerboseMonitor : public uscxml::InterpreterMonitor {
void onStableConfiguration(uscxml::Interpreter interpreter) {
printConfig(interpreter.getConfiguration());
@@ -58,20 +62,29 @@ void printUsageAndExit(const char* progName) {
printf("%s version " USCXML_VERSION " (" CMAKE_BUILD_TYPE " build - " CMAKE_COMPILER_STRING ")\n", progStr.c_str());
printf("Usage\n");
printf("\t%s", progStr.c_str());
- printf(" [-t pml|flat] [-v] [-lN]");
+ printf(" [-t pml|flat|min|tex] [-a {OPTIONS}] [-v] [-lN]");
#ifdef BUILD_AS_PLUGINS
printf(" [-p pluginPath]");
#endif
printf(" [-i URL] [-o FILE]");
printf("\n");
printf("Options\n");
- printf("\t-t flat : flatten to SCXML state-machine\n");
- printf("\t-t pml : convert to spin/promela program\n");
- printf("\t-t min : minimize SCXML state-chart\n");
- printf("\t-v : be verbose\n");
- printf("\t-lN : Set loglevel to N\n");
- printf("\t-i URL : Input file (defaults to STDIN)\n");
- printf("\t-o FILE : Output file (defaults to STDOUT)\n");
+ printf("\t-t flat : flatten to SCXML state-machine\n");
+ printf("\t-t pml : convert to spin/promela program\n");
+ printf("\t-t min : minimize SCXML state-chart\n");
+ printf("\t-t tex : write global state transition table as tex file\n");
+ printf("\t-a {OPTIONS} : annotate SCXML elements with comma seperated options\n");
+ printf("\t 'priority' - transitions with their priority for transition selection\n");
+ printf("\t 'step' - global states with their step identifier (-tflat only)\n");
+ printf("\t 'members' - global transitions with their member transitions per index (-tflat only)\n");
+ printf("\t 'sends' - transititve number of sends to external queue for global transitions (-tflat only)\n");
+ printf("\t 'raises' - transititve number of raises to internal queue for global transitions (-tflat only)\n");
+ printf("\t 'verbose' - comments detailling state changes and transitions for content selection (-tflat only)\n");
+ printf("\t 'progress' - insert comments documenting progress in dociment (-tmin only)\n");
+ printf("\t-v : be verbose\n");
+ printf("\t-lN : Set loglevel to N\n");
+ printf("\t-i URL : Input file (defaults to STDIN)\n");
+ printf("\t-o FILE : Output file (defaults to STDOUT)\n");
printf("\n");
exit(1);
}
@@ -84,7 +97,8 @@ int main(int argc, char** argv) {
std::string pluginPath;
std::string inputFile;
std::string outputFile;
-
+ std::list<std::string> annotations;
+
#if defined(HAS_SIGNAL_H) && !defined(WIN32)
signal(SIGPIPE, SIG_IGN);
#endif
@@ -99,9 +113,10 @@ int main(int argc, char** argv) {
struct option longOptions[] = {
{"verbose", no_argument, 0, 'v'},
{"type", required_argument, 0, 't'},
+ {"annotate", required_argument, 0, 'a'},
{"plugin-path", required_argument, 0, 'p'},
{"input-file", required_argument, 0, 'i'},
- {"output-file", required_argument, 0, 'o'},
+ {"output-file", required_argument, 0, 'o'},
{"loglevel", required_argument, 0, 'l'},
{0, 0, 0, 0}
};
@@ -110,7 +125,7 @@ int main(int argc, char** argv) {
int optionInd = 0;
int option;
for (;;) {
- option = getopt_long_only(argc, argv, "+vp:t:i:o:l:", longOptions, &optionInd);
+ option = getopt_long_only(argc, argv, "+vp:t:i:o:l:a:", longOptions, &optionInd);
if (option == -1) {
break;
}
@@ -132,6 +147,9 @@ int main(int argc, char** argv) {
case 'i':
inputFile = optarg;
break;
+ case 'a':
+ annotations = InterpreterImpl::tokenize(optarg, ',');
+ break;
case 'o':
outputFile = optarg;
break;
@@ -145,18 +163,45 @@ int main(int argc, char** argv) {
}
}
- if (outType.length() == 0 && outputFile.length() > 0) {
- // try to get type from outfile extension
- size_t dotPos = outputFile.find_last_of(".");
- if (dotPos != std::string::npos) {
- outType= outputFile.substr(dotPos + 1);
- }
- }
+ // make sure given annotation options are available in the environment
+ if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_STATE_STEP", "step"))
+ setenv("USCXML_ANNOTATE_GLOBAL_STATE_STEP", "YES", 1);
+
+ if (ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_PRIO", "priority"))
+ setenv("USCXML_ANNOTATE_GLOBAL_TRANS_PRIO", "YES", 1);
+
+ if (ANNOTATE("USCXML_ANNOTATE_VERBOSE_COMMENTS", "verbose"))
+ setenv("USCXML_ANNOTATE_VERBOSE_COMMENTS", "YES", 1);
+
+ if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_MEMBERS", "members"))
+ setenv("USCXML_ANNOTATE_GLOBAL_TRANS_MEMBERS", "YES", 1);
+
+ if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_SENDS", "sends"))
+ setenv("USCXML_ANNOTATE_GLOBAL_TRANS_SENDS", "YES", 1);
+
+ if(ANNOTATE("USCXML_ANNOTATE_GLOBAL_TRANS_RAISES", "raises"))
+ setenv("USCXML_ANNOTATE_GLOBAL_TRANS_RAISES", "YES", 1);
+
+ if(ANNOTATE("USCXML_ANNOTATE_PROGRESS", "progress"))
+ setenv("USCXML_ANNOTATE_PROGRESS", "YES", 1);
+
+// if (outType.length() == 0 && outputFile.length() > 0) {
+// // try to get type from outfile extension
+// size_t dotPos = outputFile.find_last_of(".");
+// if (dotPos != std::string::npos) {
+// outType= outputFile.substr(dotPos + 1);
+// }
+// }
- if (outType.length() == 0)
- printUsageAndExit(argv[0]);
+// if (outType.length() == 0)
+// printUsageAndExit(argv[0]);
- if (outType != "flat" && outType != "scxml" && outType != "pml" && outType != "min")
+ if (outType != "flat" &&
+ outType != "scxml" &&
+ outType != "pml" &&
+ outType != "min" &&
+ outType != "tex" &&
+ std::find(annotations.begin(), annotations.end(), "priority") == annotations.end())
printUsageAndExit(argv[0]);
// register plugins
@@ -200,7 +245,19 @@ int main(int argc, char** argv) {
exit(EXIT_SUCCESS);
}
- if (outType == "scxml" || outType == "flat") {
+ if (outType == "tex") {
+ if (outputFile.size() == 0 || outputFile == "-") {
+ ChartToTex::transform(interpreter).writeTo(std::cout);
+ } else {
+ std::ofstream outStream;
+ outStream.open(outputFile.c_str());
+ ChartToTex::transform(interpreter).writeTo(outStream);
+ outStream.close();
+ }
+ exit(EXIT_SUCCESS);
+ }
+
+ if (outType == "flat") {
if (outputFile.size() == 0 || outputFile == "-") {
ChartToFlatSCXML::transform(interpreter).writeTo(std::cout);
} else {
@@ -224,6 +281,24 @@ int main(int argc, char** argv) {
exit(EXIT_SUCCESS);
}
+#if 1
+ if (annotations.size() > 0) {
+ ChartToFSM annotater(interpreter);
+ if (std::find(annotations.begin(), annotations.end(), "priority") != annotations.end())
+ annotater.indexTransitions();
+
+ if (outputFile.size() == 0 || outputFile == "-") {
+ std::cout << annotater.getDocument();
+ } else {
+ std::ofstream outStream;
+ outStream.open(outputFile.c_str());
+ outStream << annotater.getDocument();
+ outStream.close();
+ }
+ exit(EXIT_SUCCESS);
+ }
+#endif
+
} catch (Event e) {
std::cout << e << std::endl;
}