diff --git a/LICENSE b/LICENSE
index 2cc3d48e9..b66a166f5 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,9 +1,9 @@
MIT License
-Developed 2012-2023 by Andreas Drewke, Dominik Hepp, Mathias Lenz, Kolja Gumpert,
+Developed 2012-2024 by Andreas Drewke, Dominik Hepp, Mathias Lenz, Kolja Gumpert,
drewke.net, mindty.com, github.com/mahula
-Copyright 2012...2023 Andreas Drewke and others if not stated differently in
+Copyright 2012...2024 Andreas Drewke and others if not stated differently in
header file.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/Makefile b/Makefile
index ad9dc73e9..a109aa78c 100644
--- a/Makefile
+++ b/Makefile
@@ -862,6 +862,7 @@ EXT_MINISCRIPT_SRCS = \
ext/miniscript/src/miniscript/os/network/TCPSocket.cpp \
ext/miniscript/src/miniscript/utilities/Base64.cpp \
ext/miniscript/src/miniscript/utilities/Console.cpp \
+ ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp \
ext/miniscript/src/miniscript/utilities/ExceptionBase.cpp \
ext/miniscript/src/miniscript/utilities/Float.cpp \
ext/miniscript/src/miniscript/utilities/Hex.cpp \
diff --git a/Makefile.nmake b/Makefile.nmake
index cbae3a12c..639ac0681 100644
--- a/Makefile.nmake
+++ b/Makefile.nmake
@@ -730,6 +730,7 @@ EXT_MINISCRIPT_SRCS = \
ext/miniscript/src/miniscript/os/network/TCPSocket.cpp \
ext/miniscript/src/miniscript/utilities/Base64.cpp \
ext/miniscript/src/miniscript/utilities/Console.cpp \
+ ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp \
ext/miniscript/src/miniscript/utilities/ExceptionBase.cpp \
ext/miniscript/src/miniscript/utilities/Float.cpp \
ext/miniscript/src/miniscript/utilities/Hex.cpp \
diff --git a/README-MiniScript.md b/README-MiniScript.md
index 34a6b517a..a3a423c35 100644
--- a/README-MiniScript.md
+++ b/README-MiniScript.md
@@ -1364,12 +1364,27 @@ end
| console.dump($value: Mixed): Null |
| Print to console |
| console.log(...): Null |
-| Print to console |
+| Print to console without trainling new line |
| console.print(...): Null |
| Print to console with a trailing new line |
| console.println(...): Null |
+| Read all input into string value |
+| console.readAll(): String |
+| Read all input into array of strings |
+| console.readAllAsArray(): Array |
+| Read a line from input |
+| console.readln(): String |
+
+## 7.4. Error console/stream methods
+
+| Table of methods |
+|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Print to error console/stream without trainling new line |
+| console.error.print(...): Null |
+| Print to error console/stream with a trailing new line |
+| console.error.println(...): Null |
-## 7.4. Cryptography Base64 methods
+## 7.5. Cryptography Base64 methods
| Table of methods |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -1378,14 +1393,14 @@ end
| Encode a string using Base64 |
| cryptography.base64.encode($value: String): String |
-## 7.5. Cryptography SHA256 methods
+## 7.6. Cryptography SHA256 methods
| Table of methods |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Hash a string using SHA256 |
| cryptography.sha256.encode($value: String): String |
-## 7.6. File System methods
+## 7.7. File System methods
| Table of methods |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -1436,7 +1451,7 @@ end
| Renames a file/folder |
| filesystem.rename($fileNameFrom: String, $fileNameTo: String): Boolean |
-## 7.7. Float methods
+## 7.8. Float methods
| Table of methods |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -1447,7 +1462,7 @@ end
| Convert float to integer bit representation of float |
| float.toIntValue($float: Float): Integer |
-## 7.8. JSON methods
+## 7.9. JSON methods
| Table of methods |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -1456,7 +1471,7 @@ end
| Serialize JSON |
| json.serialize($value: Mixed): String |
-## 7.9. Math methods
+## 7.10. Math methods
| Table of methods |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -1515,7 +1530,7 @@ end
| Compute tan |
| math.tan($x: Float): Float |
-## 7.10. HTTP/HTTPS client methods
+## 7.11. HTTP/HTTPS client methods
| Table of methods |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -1530,7 +1545,7 @@ end
| Execute a HTTP/HTTPS PUT request |
| network.httpclient.put($url: String, $data: Mixed[, $queryParameters: ?Map[, $headers: ?Map]]): ?Map|
-## 7.11. Script methods
+## 7.12. Script methods
| Table of methods |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -1557,7 +1572,7 @@ end
| Wait for condition to happen |
| script.waitForCondition(): Null |
-## 7.12. Time methods
+## 7.13. Time methods
| Table of methods |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@@ -1566,7 +1581,7 @@ end
| Get current time in milliseconds |
| time.getCurrentMillis(): Integer |
-## 7.13. XML methods
+## 7.14. XML methods
| Table of methods |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
diff --git a/ext/miniscript/LICENSE b/ext/miniscript/LICENSE
index 945b8cf45..7b388fa95 100644
--- a/ext/miniscript/LICENSE
+++ b/ext/miniscript/LICENSE
@@ -1,9 +1,9 @@
MIT License
-Developed 2021-2023 by Andreas Drewke, Dominik Hepp, Kolja Gumpert,
+Developed 2021-2024 by Andreas Drewke, Dominik Hepp, Kolja Gumpert,
drewke.net, mindty.com
-Copyright 2023 Andreas Drewke.
+Copyright 2024 Andreas Drewke.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/ext/miniscript/src/miniscript/miniscript/ApplicationMethods.cpp b/ext/miniscript/src/miniscript/miniscript/ApplicationMethods.cpp
index 506e0cb7a..412c4c4c4 100644
--- a/ext/miniscript/src/miniscript/miniscript/ApplicationMethods.cpp
+++ b/ext/miniscript/src/miniscript/miniscript/ApplicationMethods.cpp
@@ -1,5 +1,6 @@
#include
#include
+#include
#include
#include
@@ -21,6 +22,43 @@ using _Console = miniscript::utilities::Console;
using _StringTools = miniscript::utilities::StringTools;
void ApplicationMethods::registerConstants(MiniScript* miniScript) {
+ miniScript->setConstant("$APPLICATION::EXITCODE_SUCCESS", static_cast(EXIT_SUCCESS));
+ miniScript->setConstant("$APPLICATION::EXITCODE_FAILURE", static_cast(EXIT_FAILURE));
+ //
+ #if defined(__FreeBSD__)
+ miniScript->setConstant("$APPLICATION::OS", string("FreeBSD"));
+ #elif defined(__HAIKU__)
+ miniScript->setConstant("$APPLICATION::OS", string("Haiku"));
+ #elif defined(__linux__)
+ miniScript->setConstant("$APPLICATION::OS", string("Linux"));
+ #elif defined(__APPLE__)
+ miniScript->setConstant("$APPLICATION::OS", string("MacOSX"));
+ #elif defined(__NetBSD__)
+ miniScript->setConstant("$APPLICATION::OS", string("NetBSD"));
+ #elif defined(__OpenBSD__)
+ miniScript->setConstant("$APPLICATION::OS", string("OpenBSD"));
+ #elif defined(_MSC_VER)
+ miniScript->setConstant("$APPLICATION::OS", string("Windows-MSC"));
+ #elif defined(_WIN32)
+ miniScript->setConstant("$APPLICATION::OS", string("Windows-MINGW"));
+ #else
+ miniScript->setConstant("$APPLICATION::OS", string("Unknown"));
+ #endif
+ #if defined(__amd64__) || defined(_M_X64)
+ miniScript->setConstant("$APPLICATION::CPU", string("X64"));
+ #elif defined(__ia64__) || defined(_M_IA64)
+ miniScript->setConstant("$APPLICATION::CPU", string("IA64"));
+ #elif defined(__aarch64__)
+ miniScript->setConstant("$APPLICATION::CPU", string("ARM64"));
+ #elif defined(__arm__) || defined(_M_ARM)
+ miniScript->setConstant("$APPLICATION::CPU", string("ARM"));
+ #elif defined(__powerpc64__)
+ miniScript->setConstant("$APPLICATION::CPU", string("PPC64"));
+ #elif defined(__powerpc__)
+ miniScript->setConstant("$APPLICATION::CPU", string("PPC"));
+ #else
+ miniScript->setConstant("$APPLICATION::CPU", string("Unknown"));
+ #endif
}
const string ApplicationMethods::execute(const string& command) {
@@ -95,5 +133,35 @@ void ApplicationMethods::registerMethods(MiniScript* miniScript) {
};
miniScript->registerMethod(new MethodApplicationGetArguments(miniScript));
}
+ {
+ //
+ class MethodApplicationExit: public MiniScript::Method {
+ private:
+ MiniScript* miniScript { nullptr };
+ public:
+ MethodApplicationExit(MiniScript* miniScript):
+ MiniScript::Method(
+ {
+ { .type = MiniScript::TYPE_INTEGER, .name = "exitCode", .optional = true, .reference = false, .nullable = false },
+ }
+ ),
+ miniScript(miniScript) {}
+ const string getMethodName() override {
+ return "application.exit";
+ }
+ void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override {
+ int64_t exitCode = 0ll;
+ if (MiniScript::getIntegerValue(arguments, 0, exitCode, true) == true) {
+ miniScript->getContext()->setExitCode(static_cast(exitCode));
+ miniScript->stopScriptExecution();
+ miniScript->stopRunning();
+ } else {
+ _Console::println(getMethodName() + "(): " + miniScript->getStatementInformation(statement) + ": argument mismatch: expected arguments: " + miniScript->getArgumentInformation(getMethodName()));
+ miniScript->startErrorScript();
+ }
+ }
+ };
+ miniScript->registerMethod(new MethodApplicationExit(miniScript));
+ }
}
}
diff --git a/ext/miniscript/src/miniscript/miniscript/ConsoleMethods.cpp b/ext/miniscript/src/miniscript/miniscript/ConsoleMethods.cpp
index dd100fb61..d89a6ee2d 100644
--- a/ext/miniscript/src/miniscript/miniscript/ConsoleMethods.cpp
+++ b/ext/miniscript/src/miniscript/miniscript/ConsoleMethods.cpp
@@ -1,10 +1,14 @@
+#include
#include
#include
#include
#include
#include
+#include
+using std::cin;
+using std::getline;
using std::span;
using miniscript::miniscript::ConsoleMethods;
@@ -12,6 +16,7 @@ using miniscript::miniscript::ConsoleMethods;
using miniscript::miniscript::MiniScript;
using _Console = miniscript::utilities::Console;
+using _ErrorConsole = miniscript::utilities::ErrorConsole;
void ConsoleMethods::registerConstants(MiniScript* miniScript) {
}
@@ -110,4 +115,110 @@ void ConsoleMethods::registerMethods(MiniScript* miniScript) {
};
miniScript->registerMethod(new MethodConsolePrintln(miniScript));
}
+ {
+ //
+ class MethodConsoleReadln: public MiniScript::Method {
+ private:
+ MiniScript* miniScript { nullptr };
+ public:
+ MethodConsoleReadln(MiniScript* miniScript):
+ MiniScript::Method({}, MiniScript::TYPE_STRING),
+ miniScript(miniScript) {
+ //
+ }
+ const string getMethodName() override {
+ return "console.readln";
+ }
+ void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override {
+ returnValue.setValue(_Console::readln());
+ }
+ };
+ miniScript->registerMethod(new MethodConsoleReadln(miniScript));
+ }
+ {
+ //
+ class MethodConsoleReadAll: public MiniScript::Method {
+ private:
+ MiniScript* miniScript { nullptr };
+ public:
+ MethodConsoleReadAll(MiniScript* miniScript):
+ MiniScript::Method({}, MiniScript::TYPE_STRING),
+ miniScript(miniScript) {
+ //
+ }
+ const string getMethodName() override {
+ return "console.readAll";
+ }
+ void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override {
+ returnValue.setValue(_Console::readAll());
+ }
+ };
+ miniScript->registerMethod(new MethodConsoleReadAll(miniScript));
+ }
+ {
+ //
+ class MethodConsoleReadAllAsArray: public MiniScript::Method {
+ private:
+ MiniScript* miniScript { nullptr };
+ public:
+ MethodConsoleReadAllAsArray(MiniScript* miniScript):
+ MiniScript::Method({}, MiniScript::TYPE_ARRAY),
+ miniScript(miniScript) {
+ //
+ }
+ const string getMethodName() override {
+ return "console.readAllAsArray";
+ }
+ void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override {
+ returnValue.setType(MiniScript::TYPE_ARRAY);
+ const auto input = _Console::readAllAsArray();
+ for (const auto& line: input) returnValue.pushArrayEntry(MiniScript::Variable(line));
+ }
+ };
+ miniScript->registerMethod(new MethodConsoleReadAllAsArray(miniScript));
+ }
+ {
+ //
+ class MethodConsoleErrorPrint: public MiniScript::Method {
+ private:
+ MiniScript* miniScript { nullptr };
+ public:
+ MethodConsoleErrorPrint(MiniScript* miniScript): MiniScript::Method(), miniScript(miniScript) {}
+ const string getMethodName() override {
+ return "console.error.print";
+ }
+ void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override {
+ for (const auto& argument: arguments) {
+ _ErrorConsole::print(argument.getValueAsString());
+ }
+ }
+ bool isVariadic() const override {
+ return true;
+ }
+ };
+ miniScript->registerMethod(new MethodConsoleErrorPrint(miniScript));
+ }
+ {
+ //
+ class MethodConsoleErrorPrintln: public MiniScript::Method {
+ private:
+ MiniScript* miniScript { nullptr };
+ public:
+ MethodConsoleErrorPrintln(MiniScript* miniScript): MiniScript::Method(), miniScript(miniScript) {}
+ const string getMethodName() override {
+ return "console.error.println";
+ }
+ void executeMethod(span& arguments, MiniScript::Variable& returnValue, const MiniScript::Statement& statement) override {
+ for (const auto& argument: arguments) {
+ _ErrorConsole::print(argument.getValueAsString());
+ }
+ _ErrorConsole::println();
+ }
+ bool isVariadic() const override {
+ return true;
+ }
+ };
+ miniScript->registerMethod(new MethodConsoleErrorPrintln(miniScript));
+ }
}
+
diff --git a/ext/miniscript/src/miniscript/miniscript/Context.h b/ext/miniscript/src/miniscript/miniscript/Context.h
index edcb3e755..1264752ba 100644
--- a/ext/miniscript/src/miniscript/miniscript/Context.h
+++ b/ext/miniscript/src/miniscript/miniscript/Context.h
@@ -23,6 +23,7 @@ class miniscript::miniscript::Context
unordered_map scriptsById;
vector scriptCallStack;
vector argumentValues;
+ int exitCode { 0 };
public:
// forbid class copy
@@ -103,4 +104,19 @@ class miniscript::miniscript::Context
scriptCallStack.erase(scriptCallStack.begin() + scriptCallStack.size() - 1);
}
+ /**
+ * Set exit code
+ * @param exitCode exit code
+ */
+ inline void setExitCode(int exitCode) {
+ this->exitCode = exitCode;
+ }
+
+ /**
+ * @return exit code
+ */
+ inline int getExitCode() {
+ return exitCode;
+ }
+
};
diff --git a/ext/miniscript/src/miniscript/miniscript/MiniScript.cpp b/ext/miniscript/src/miniscript/miniscript/MiniScript.cpp
index fd94610cd..2559ad5d3 100644
--- a/ext/miniscript/src/miniscript/miniscript/MiniScript.cpp
+++ b/ext/miniscript/src/miniscript/miniscript/MiniScript.cpp
@@ -1,5 +1,9 @@
#include
+#if defined(_MSC_VER)
+ #include
+#endif
+
#include
#include
#include
@@ -125,6 +129,10 @@ const string MiniScript::Variable::TYPENAME_SET = "Set";
const vector MiniScript::Method::CONTEXTFUNCTIONS_ALL = {};
void MiniScript::initialize() {
+ //
+ #if defined(_MSC_VER)
+ SetConsoleOutputCP(65001);
+ #endif
//
registerDataType(new HTTPDownloadClientClass());
//
@@ -785,7 +793,7 @@ bool MiniScript::createStatementSyntaxTree(const string_view& methodName, const
if (viewIsVariableAccess(argument) == true) {
//
Variable value;
- value.setValue(deescape(argument));
+ value.setValue(deescape(argument, statement));
// look up getVariable method
string methodName = argumentIdx >= argumentReferences.size() || argumentReferences[argumentIdx] == false?"getVariable":"getVariableReference";
@@ -805,7 +813,7 @@ bool MiniScript::createStatementSyntaxTree(const string_view& methodName, const
syntaxTree.arguments.emplace_back(
SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD,
- MiniScript::Variable(deescape(methodName)),
+ MiniScript::Variable(deescape(methodName, statement)),
method,
initializer_list
{
@@ -853,7 +861,7 @@ bool MiniScript::createStatementSyntaxTree(const string_view& methodName, const
_StringTools::viewEndsWith(argument, "'") == true)) {
//
Variable value;
- value.setValue(deescape(_StringTools::viewSubstring(argument, 1, argument.size() - 1)));
+ value.setValue(deescape(_StringTools::viewSubstring(argument, 1, argument.size() - 1), statement));
//
syntaxTree.arguments.emplace_back(
SyntaxTreeNode::SCRIPTSYNTAXTREENODE_LITERAL,
@@ -880,7 +888,7 @@ bool MiniScript::createStatementSyntaxTree(const string_view& methodName, const
// try first user functions
if (functionIdx != SCRIPTIDX_NONE) {
syntaxTree.type = SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_FUNCTION;
- syntaxTree.value.setValue(deescape(methodName));
+ syntaxTree.value.setValue(deescape(methodName, statement));
syntaxTree.setFunctionScriptIdx(functionIdx);
//
return true;
@@ -888,7 +896,7 @@ bool MiniScript::createStatementSyntaxTree(const string_view& methodName, const
// try methods next
if (method != nullptr) {
syntaxTree.type = SyntaxTreeNode::SCRIPTSYNTAXTREENODE_EXECUTE_METHOD;
- syntaxTree.value.setValue(deescape(methodName));
+ syntaxTree.value.setValue(deescape(methodName, statement));
syntaxTree.setMethod(method);
//
return true;
diff --git a/ext/miniscript/src/miniscript/miniscript/MiniScript.h b/ext/miniscript/src/miniscript/miniscript/MiniScript.h
index 211ceeb8e..21c7f4376 100644
--- a/ext/miniscript/src/miniscript/miniscript/MiniScript.h
+++ b/ext/miniscript/src/miniscript/miniscript/MiniScript.h
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -46,6 +47,7 @@ using _Character = miniscript::utilities::Character;
using _Console = miniscript::utilities::Console;
using _Exception = miniscript::utilities::Exception;
using _Float = miniscript::utilities::Float;
+using _Hex = miniscript::utilities::Hex;
using _Integer = miniscript::utilities::Integer;
using _StringTools = miniscript::utilities::StringTools;
using _Time = miniscript::utilities::Time;
@@ -58,6 +60,7 @@ using _Library = miniscript::miniscript::Library;
* @author Andreas Drewke
*/
class miniscript::miniscript::MiniScript {
+ friend class ApplicationMethods;
friend class BaseMethods;
friend class JSONMethods;
friend class ScriptMethods;
@@ -1967,7 +1970,7 @@ class miniscript::miniscript::MiniScript {
if (viewIsVariableAccess(value) == true) {
setFunctionCallStatement("getVariable(\"" + string(value) + "\")", miniScript, statement);
} else {
- setValue(deescape(value));
+ setValue(miniScript->deescape(value, statement));
}
}
@@ -3147,15 +3150,52 @@ class miniscript::miniscript::MiniScript {
/**
* Deescape string
* @param str string
+ * @param statement statement
* @return deescaped string
*/
- inline static const string deescape(const string_view& str) {
+ inline const string deescape(const string_view& str, const Statement& statement) {
string deescapedStr;
auto lc = '\0';
for (auto i = 0; i < str.size(); i++) {
auto c = str[i];
if (c != '\\' || lc == '\\') {
- deescapedStr+= c;
+ // escape sequences
+ // see: https://en.cppreference.com/w/cpp/language/escape
+ // \0 null character
+ if (lc == '\\' && c == '0') deescapedStr+= '\0'; else
+ // \a audible bell
+ if (lc == '\\' && c == 'a') deescapedStr+= '\a'; else
+ // \b backspace
+ if (lc == '\\' && c == 'b') deescapedStr+= '\b'; else
+ // \f form feed - new page
+ if (lc == '\\' && c == 'f') deescapedStr+= '\f'; else
+ // \n line feed - new line
+ if (lc == '\\' && c == 'n') deescapedStr+= '\n'; else
+ // \r carriage return
+ if (lc == '\\' && c == 'r') deescapedStr+= '\r'; else
+ // \t horizontal tab
+ if (lc == '\\' && c == 't') deescapedStr+= '\t'; else
+ // \v vertical tab
+ if (lc == '\\' && c == 'v') deescapedStr+= '\v'; else
+ // unicode \Unnnnnnnn
+ if (lc == '\\' && c == 'U') {
+ string unicodeHexadecimalSequence;
+ auto j = 0;
+ auto valid = true;
+ for (i++; i < str.size() && j < 8; i++ && j++) {
+ c = str[i];
+ unicodeHexadecimalSequence+= c;
+ if (((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) == false) break;
+ }
+ i--;
+ if (valid == false || j != 8) {
+ _Console::println(getStatementInformation(statement) + ": Invalid hexadecimal unicode character sequence: " + unicodeHexadecimalSequence);
+ } else {
+ _Character::appendToString(deescapedStr, _Hex::decodeInt(unicodeHexadecimalSequence));
+ }
+ } else
+ deescapedStr+= c;
+ //
lc = '\0';
continue;
}
diff --git a/ext/miniscript/src/miniscript/miniscript/Transpiler.cpp b/ext/miniscript/src/miniscript/miniscript/Transpiler.cpp
index 1108c6058..28bf1a009 100644
--- a/ext/miniscript/src/miniscript/miniscript/Transpiler.cpp
+++ b/ext/miniscript/src/miniscript/miniscript/Transpiler.cpp
@@ -1359,7 +1359,7 @@ void Transpiler::generateArrayAccessMethods(
if (arrayAccessStatementAsScriptVariable.getFloatValue(floatValue) == true) {
generatedDefinitions+= lamdaIndent + "// Miniscript transpilation for a " + (condition == true?"condition":"statement") + " array access statement, statement index " + to_string(statement.statementIdx) + ", argument indices " + MiniScript::getArgumentIndicesAsString(nextArgumentIndices, ", ") + ", array access statement index " + to_string(arrayAccessStatementIdx) + "\n";
generatedDefinitions+= lamdaIndent + "auto array_access_statement_" + to_string(statement.statementIdx) + "_" + MiniScript::getArgumentIndicesAsString(nextArgumentIndices, "_") + "_" + to_string(arrayAccessStatementIdx) + " = [&](const Statement& statement) -> Variable {" + "\n";
- generatedDefinitions+= lamdaIndent + " return Variable(static_cast(" + to_string(static_cast(floatValue)) + "ll));" + "\n"; + "\n";
+ generatedDefinitions+= lamdaIndent + " return Variable(static_cast(" + to_string(static_cast(floatValue)) + "ll));" + "\n";
generatedDefinitions+= lamdaIndent + "};" + "\n";
}
// literals
diff --git a/ext/miniscript/src/miniscript/tools/miniscript-main.cpp b/ext/miniscript/src/miniscript/tools/miniscript-main.cpp
index 7c579a5c6..d978c4d04 100644
--- a/ext/miniscript/src/miniscript/tools/miniscript-main.cpp
+++ b/ext/miniscript/src/miniscript/tools/miniscript-main.cpp
@@ -164,6 +164,7 @@ int main(int argc, char** argv)
//
if (script->isValid() == false) {
Console::println(pathToScript + ": Script not valid. Exiting!");
+ return EXIT_SUCCESS;
} else {
// TODO: we need a MiniScript startup routine
Network::initialize();
@@ -181,6 +182,8 @@ int main(int argc, char** argv)
}
context->pop();
}
+ } else {
+ return EXIT_FAILURE;
}
} else
if (version == false) {
@@ -202,5 +205,5 @@ int main(int argc, char** argv)
}
//
- return script == nullptr || script->isValid() == false?EXIT_FAILURE:EXIT_SUCCESS;
+ return context->getExitCode();
}
diff --git a/ext/miniscript/src/miniscript/utilities/Console.cpp b/ext/miniscript/src/miniscript/utilities/Console.cpp
index 00b392a2a..c1af21b31 100644
--- a/ext/miniscript/src/miniscript/utilities/Console.cpp
+++ b/ext/miniscript/src/miniscript/utilities/Console.cpp
@@ -1,11 +1,19 @@
#include
#include
+#include
+#include
#include
#include
#include
-using namespace std;
+using std::cin;
+using std::cout;
+using std::endl;
+using std::getline;
+using std::string;
+using std::string_view;
+using std::vector;
using miniscript::utilities::Console;
@@ -26,3 +34,28 @@ void Console::println()
cout << endl;
cout.flush();
}
+
+const string Console::readln()
+{
+ string line;
+ getline(cin, line);
+ return line;
+}
+
+const string Console::readAll() {
+ string line;
+ string result;
+ while (cin.eof() == false && getline(cin, line)) {
+ result+= line + "\n";
+ }
+ return line;
+}
+
+const vector Console::readAllAsArray() {
+ vector result;
+ string line;
+ while (cin.eof() == false && getline(cin, line)) {
+ result.push_back(line);
+ }
+ return result;
+}
diff --git a/ext/miniscript/src/miniscript/utilities/Console.h b/ext/miniscript/src/miniscript/utilities/Console.h
index 605eb653c..555a3ccf6 100644
--- a/ext/miniscript/src/miniscript/utilities/Console.h
+++ b/ext/miniscript/src/miniscript/utilities/Console.h
@@ -1,11 +1,15 @@
#pragma once
+#include
#include
+#include
#include
#include
+using std::string;
using std::string_view;
+using std::vector;
/**
* Console class
@@ -22,14 +26,29 @@ class miniscript::utilities::Console
static void println(const string_view& str);
/**
- * Print given string
+ * Print given string without trainling newline to console
* @param str string
*/
static void print(const string_view& str);
/**
- * Print new line to console
+ * Print newline to console
*/
static void println();
+ /**
+ * Read line from console
+ */
+ static const string readln();
+
+ /**
+ * Read all input from console into string
+ */
+ static const string readAll();
+
+ /**
+ * Read all input from console into string vector
+ */
+ static const vector readAllAsArray();
+
};
diff --git a/ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp b/ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp
new file mode 100644
index 000000000..1f28a25a5
--- /dev/null
+++ b/ext/miniscript/src/miniscript/utilities/ErrorConsole.cpp
@@ -0,0 +1,28 @@
+#include
+#include
+
+#include
+#include
+
+using std::cerr;
+using std::endl;
+
+using miniscript::utilities::ErrorConsole;
+
+void ErrorConsole::println(const string_view& str)
+{
+ cerr << str << endl;
+ cerr.flush();
+}
+
+void ErrorConsole::print(const string_view& str)
+{
+ cerr << str;
+ cerr.flush();
+}
+
+void ErrorConsole::println()
+{
+ cerr << endl;
+ cerr.flush();
+}
diff --git a/ext/miniscript/src/miniscript/utilities/ErrorConsole.h b/ext/miniscript/src/miniscript/utilities/ErrorConsole.h
new file mode 100644
index 000000000..2c3c8404a
--- /dev/null
+++ b/ext/miniscript/src/miniscript/utilities/ErrorConsole.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include
+
+#include
+#include
+
+using std::string_view;
+
+/**
+ * Console class
+ * @author Andreas Drewke
+ * @versio $Id$
+ */
+class miniscript::utilities::ErrorConsole
+{
+public:
+ /**
+ * Print given string and trailing newline to error console
+ * @param str string
+ */
+ static void println(const string_view& str);
+
+ /**
+ * Print given string to error console without trainling new line
+ * @param str string
+ */
+ static void print(const string_view& str);
+
+ /**
+ * Print newline to error console
+ */
+ static void println();
+
+};
diff --git a/ext/miniscript/src/miniscript/utilities/fwd-miniscript.h b/ext/miniscript/src/miniscript/utilities/fwd-miniscript.h
index 8037c217b..01a604ad0 100644
--- a/ext/miniscript/src/miniscript/utilities/fwd-miniscript.h
+++ b/ext/miniscript/src/miniscript/utilities/fwd-miniscript.h
@@ -6,6 +6,7 @@ namespace utilities {
class Base64;
class Character;
class Console;
+ class ErrorConsole;
class ExceptionBase;
class Float;
class Hex;
diff --git a/resources/engine/code-completion/tscript-methods.properties b/resources/engine/code-completion/tscript-methods.properties
index fa64b79c6..5d97e362f 100644
--- a/resources/engine/code-completion/tscript-methods.properties
+++ b/resources/engine/code-completion/tscript-methods.properties
@@ -92,6 +92,7 @@ miniscript.basemethod.group.cryptography.base64=Cryptography Base64 methods
miniscript.basemethod.group.cryptography.sha256=Cryptography SHA256 methods
miniscript.basemethod.group.context.script=Script container and interoperability methods
miniscript.basemethod.group.console=Console methods
+miniscript.basemethod.group.console.error=Error console/stream methods
miniscript.basemethod.group.filesystem=File System methods
miniscript.basemethod.group.float=Float methods
miniscript.basemethod.group.json=JSON methods
@@ -133,6 +134,7 @@ miniscript.basemethod.add=Add
miniscript.basemethod.and=Logical and
miniscript.basemethod.application.getArguments=Get application command line arguments
miniscript.basemethod.application.execute=Execute Application
+miniscript.basemethod.application.exit=Exit application with optional exit code
miniscript.basemethod.Array=Create array
miniscript.basemethod.Array::get=Get array entry
miniscript.basemethod.Array::set=Set array entry
@@ -184,9 +186,14 @@ miniscript.basemethod.cryptography.base64.encode=Encode a string using Base64
miniscript.basemethod.cryptography.base64.decode=Decode a Base64 encoded string
miniscript.basemethod.cryptography.sha256.encode=Hash a string using SHA256
miniscript.basemethod.console.dump=Pretty print variable to console
+miniscript.basemethod.console.error.print=Print to error console/stream without trainling new line
+miniscript.basemethod.console.error.println=Print to error console/stream with a trailing new line
miniscript.basemethod.console.log=Print to console
-miniscript.basemethod.console.print=Print to console
+miniscript.basemethod.console.print=Print to console without trainling new line
miniscript.basemethod.console.println=Print to console with a trailing new line
+miniscript.basemethod.console.readAll=Read all input into string value
+miniscript.basemethod.console.readAllAsArray=Read all input into array of strings
+miniscript.basemethod.console.readln=Read a line from input
miniscript.basemethod.context.script.hasCallable=Returns if a script has a specific callable function
miniscript.basemethod.context.script.getScriptIds=Returns all script ids of its context
miniscript.basemethod.context.script.call=Call a script callable function
diff --git a/resources/miniscript/documentation/method-descriptions.properties b/resources/miniscript/documentation/method-descriptions.properties
index 5dabdf0d6..18a5036ea 100644
--- a/resources/miniscript/documentation/method-descriptions.properties
+++ b/resources/miniscript/documentation/method-descriptions.properties
@@ -13,6 +13,7 @@ miniscript.basemethod.group.cryptography.base64=Cryptography Base64 methods
miniscript.basemethod.group.cryptography.sha256=Cryptography SHA256 methods
miniscript.basemethod.group.context.script=Script container and interoperability methods
miniscript.basemethod.group.console=Console methods
+miniscript.basemethod.group.console.error=Error console/stream methods
miniscript.basemethod.group.filesystem=File System methods
miniscript.basemethod.group.float=Float methods
miniscript.basemethod.group.json=JSON methods
@@ -54,6 +55,7 @@ miniscript.basemethod.add=Add
miniscript.basemethod.and=Logical and
miniscript.basemethod.application.getArguments=Get application command line arguments
miniscript.basemethod.application.execute=Execute Application
+miniscript.basemethod.application.exit=Exit application with optional exit code
miniscript.basemethod.Array=Create array
miniscript.basemethod.Array::get=Get array entry
miniscript.basemethod.Array::set=Set array entry
@@ -73,6 +75,7 @@ miniscript.basemethod.bitwiseOr=Bitwise or
miniscript.basemethod.bitwiseXor=Bitwise xor
miniscript.basemethod.bool=Create bool
miniscript.basemethod.break=Break out of current forCondition or forTime loop
+miniscript.basemethod.case=Begins a case block within a switch block, which will be executed if the case value has matched
miniscript.basemethod.continue=Continue to next iteration of forCondition or forTime loop
miniscript.basemethod.ByteArray=Create byte array
miniscript.basemethod.ByteArray::clear=Clear byte array
@@ -104,14 +107,20 @@ miniscript.basemethod.cryptography.base64.encode=Encode a string using Base64
miniscript.basemethod.cryptography.base64.decode=Decode a Base64 encoded string
miniscript.basemethod.cryptography.sha256.encode=Hash a string using SHA256
miniscript.basemethod.console.dump=Pretty print variable to console
+miniscript.basemethod.console.error.print=Print to error console/stream without trainling new line
+miniscript.basemethod.console.error.println=Print to error console/stream with a trailing new line
miniscript.basemethod.console.log=Print to console
-miniscript.basemethod.console.print=Print to console
+miniscript.basemethod.console.print=Print to console without trainling new line
miniscript.basemethod.console.println=Print to console with a trailing new line
+miniscript.basemethod.console.readAll=Read all input into string value
+miniscript.basemethod.console.readAllAsArray=Read all input into array of strings
+miniscript.basemethod.console.readln=Read a line from input
miniscript.basemethod.context.script.hasCallable=Returns if a script has a specific callable function
miniscript.basemethod.context.script.getScriptIds=Returns all script ids of its context
miniscript.basemethod.context.script.call=Call a script callable function
miniscript.basemethod.context.script.loadScript=Load a script into context
miniscript.basemethod.context.script.removeScript=Remove a script from context
+miniscript.basemethod.default=Begins a default block within a switch block, which will be executed if no case value has matched
miniscript.basemethod.div=Divide
miniscript.basemethod.else=Else
miniscript.basemethod.elseif=Else if
@@ -215,6 +224,7 @@ miniscript.basemethod.script.evaluate=Evaluate a script statement
miniscript.basemethod.script.stop=Stop script
miniscript.basemethod.script.wait=Wait for given milliseconds
miniscript.basemethod.script.waitForCondition=Wait for condition to happen
+miniscript.basemethod.switch=Begins switch block to match a given value to case values or a default
miniscript.basemethod.Set=Create set
miniscript.basemethod.Set::has=Has key in set
miniscript.basemethod.Set::getKeys=Get set keys
diff --git a/resources/miniscript/tests/application-test.tscript b/resources/miniscript/tests/application-test.tscript
index 0981f1e8b..7800a7f62 100644
--- a/resources/miniscript/tests/application-test.tscript
+++ b/resources/miniscript/tests/application-test.tscript
@@ -13,9 +13,12 @@ on: nothing
console.log("---------------------------")
console.log()
console.log("application.getArguments(): " + application.getArguments())
- console.log("application.execute('ls'): " + application.execute('ls'))
- #
- script.stop()
+ if ($APPLICATION::OS == "Windows-MSC")
+ console.log("application.execute('dir'): " + application.execute('dir'))
+ else
+ console.log("application.execute('ls'): " + application.execute('ls'))
+ end
+ application.exit(2)
end
# an error has occurred
diff --git a/resources/miniscript/tests/console-test.tscript b/resources/miniscript/tests/console-test.tscript
new file mode 100644
index 000000000..dc8417db0
--- /dev/null
+++ b/resources/miniscript/tests/console-test.tscript
@@ -0,0 +1,30 @@
+# initialize
+on: initialize
+ console.log("--------------------------")
+ console.log("console-test: Initialize")
+ console.log("--------------------------")
+ console.log()
+end
+
+# if no condition is met, nothing will be executed, lol :D
+on: nothing
+ console.log("-----------------------")
+ console.log("console-test: Nothing")
+ console.log("-----------------------")
+ console.log()
+ console.print("Whats your name: ")
+ $name = console.readln()
+ console.println("You have the mighty name: " + $name)
+ console.error.print("Now printing your name to error console: ")
+ console.error.println($name)
+ script.stop()
+end
+
+# an error has occurred
+on: error
+ console.log("---------------------")
+ console.log("console-test: Error")
+ console.log("---------------------")
+ console.log("An error occurred")
+ script.stop()
+end
diff --git a/resources/miniscript/tests/network-test.tscript b/resources/miniscript/tests/network-test.tscript
index 5e2318377..fc593fb0e 100644
--- a/resources/miniscript/tests/network-test.tscript
+++ b/resources/miniscript/tests/network-test.tscript
@@ -36,16 +36,22 @@ on: nothing
end
#
$httpDownloadClient = HTTPDownloadClient()
- $httpDownloadClient->setURL("https://mindty.com")
- $httpDownloadClient->setFile("mindty.com.html")
+ $httpDownloadClient->setURL("https://download.freebsd.org/releases/ISO-IMAGES/14.0/FreeBSD-14.0-RELEASE-amd64-bootonly.iso")
+ $httpDownloadClient->setFile("FreeBSD-14.0-RELEASE-amd64-bootonly.iso")
+ $httpDownloadClient->setHeaders({a: 1})
console.log("HTTP download client: " + $httpDownloadClient)
- $httpDownloadClient->execute()
+ $httpDownloadClient->start()
+ console.print("[")
forCondition($httpDownloadClient->isFinished() == false)
- console.log($httpDownloadClient->getProgress())
+ console.print("-")
script.wait(1000)
end
- if (filesystem.removeFile(".", "mindty.com.html") == false)
- console.log("Could not remove file mindty.com.html.")
+ console.println("]")
+ $httpDownloadClient->join()
+ console.log("HTTP Download status code: " + $httpDownloadClient->getStatusCode())
+ console.log("HTTP Download response headers: " + $httpDownloadClient->getResponseHeaders())
+ if (filesystem.removeFile(".", "FreeBSD-14.0-RELEASE-amd64-bootonly.iso") == false)
+ console.log("Could not remove file FreeBSD-14.0-RELEASE-amd64-bootonly.iso.")
end
#
script.stop()
@@ -58,4 +64,4 @@ on: error
console.log("---------------------")
console.log("An error occurred")
script.stop()
-end
\ No newline at end of file
+end
diff --git a/resources/miniscript/tests/pipe-test.tscript b/resources/miniscript/tests/pipe-test.tscript
new file mode 100644
index 000000000..032972141
--- /dev/null
+++ b/resources/miniscript/tests/pipe-test.tscript
@@ -0,0 +1,29 @@
+# initialize
+on: initialize
+ console.log("-----------------------")
+ console.log("pipe-test: Initialize")
+ console.log("-----------------------")
+ console.log()
+end
+
+# if no condition is met, nothing will be executed, lol :D
+on: nothing
+ console.log("--------------------")
+ console.log("pipe-test: Nothing")
+ console.log("--------------------")
+ console.log()
+ console.println("Reading from pipe or console input stream: ")
+ $input = console.readAllAsArray()
+ console.println("Input was: ")
+ console.println($input)
+ script.stop()
+end
+
+# an error has occurred
+on: error
+ console.log("-------------------")
+ console.log("pipe-test: Error")
+ console.log("-------------------")
+ console.log("An error occurred")
+ script.stop()
+end
\ No newline at end of file
diff --git a/resources/miniscript/tests/string-test.tscript b/resources/miniscript/tests/string-test.tscript
new file mode 100644
index 000000000..8a10f5505
--- /dev/null
+++ b/resources/miniscript/tests/string-test.tscript
@@ -0,0 +1,29 @@
+# initialize
+on: initialize
+ console.log("-------------------------")
+ console.log("string-test: Initialize")
+ console.log("-------------------------")
+ console.log()
+end
+
+# if no condition is met, nothing will be executed, lol :D
+on: nothing
+ console.log("----------------------")
+ console.log("string-test: Nothing")
+ console.log("----------------------")
+ console.log()
+ console.println("Hi, lets produce\na newline, and\nanother one: \"yarrrrr\"")
+ console.println("Some Umlauts love: äöü >>> ÄÖÜ")
+ console.println("Some more Umlauts love: \U000000fc")
+ console.println("Beep\a")
+ script.stop()
+end
+
+# an error has occurred
+on: error
+ console.log("--------------------")
+ console.log("string-test: Error")
+ console.log("--------------------")
+ console.log("An error occurred")
+ script.stop()
+end
diff --git a/resources/miniscript/tests/switch-test.tscript b/resources/miniscript/tests/switch-test.tscript
new file mode 100644
index 000000000..3c50b320c
--- /dev/null
+++ b/resources/miniscript/tests/switch-test.tscript
@@ -0,0 +1,54 @@
+# initialize
+on: initialize
+ console.log("-------------------------")
+ console.log("switch-test: Initialize")
+ console.log("-------------------------")
+ console.log()
+end
+
+# if no condition is met, nothing will be executed, lol :D
+on: nothing
+ console.log("----------------------")
+ console.log("switch-test: Nothing")
+ console.log("----------------------")
+ console.log()
+ #
+ $i = 1
+ $j = b
+ switch($i)
+ case(0)
+ console.log("$i = 0")
+ end
+ case(1)
+ console.log("$i = 1")
+ switch($j)
+ case("a")
+ console.log("$j = a")
+ end
+ case("b")
+ console.log("$j = b")
+ end
+ case("c")
+ console.log("$j = c")
+ end
+ end
+ end
+ case(2)
+ console.log("$i = 2")
+ end
+ default
+ console.log("default: $i = " + $i)
+ end
+ end
+ #
+ script.stop()
+end
+
+# an error has occurred
+on: error
+ console.log("--------------------")
+ console.log("switch-test: Error")
+ console.log("--------------------")
+ console.log("An error occurred")
+ script.stop()
+end
\ No newline at end of file