/[svn]/linuxsampler/trunk/src/ls_instr_script.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/ls_instr_script.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2974 - (show annotations) (download)
Fri Jul 22 15:51:40 2016 UTC (7 years, 9 months ago) by schoenebeck
File size: 9592 byte(s)
* ScriptVM: Implemented automatic suspension of RT safety
  threatening scripts.
* Bumped version (2.0.0.svn25).

1 /*
2 * Copyright (c) 2014-2016 Christian Schoenebeck
3 *
4 * http://www.linuxsampler.org
5 *
6 * This program is part of LinuxSampler and released under the same terms.
7 * See README file for details.
8 */
9
10 #include "common/global.h"
11 #include "scriptvm/ScriptVM.h"
12 #include "shell/CFmt.h"
13 #include "engines/common/InstrumentScriptVM.h"
14 #include "engines/gig/InstrumentScriptVM.h"
15 #include <iostream>
16
17 /*
18 This command line tool is currently merely for development and testing
19 purposes, regarding the real-time instrument script feature of the sampler.
20 You can use this command line application like this:
21
22 ls_instr_script core < src/scriptvm/examples/helloworld.txt
23
24 Which will peform 3 things:
25
26 1. Parses the given instrument script and prints any parser errors or
27 warnings.
28 2. It dumps the parsed VM tree (only interesting for LS developers).
29 3. If there were not parser errors, it will run each event handler defined in
30 the script.
31 */
32
33 using namespace LinuxSampler;
34 using namespace std;
35
36 static void printUsage() {
37 cout << "ls_instr_script - Parse real-time instrument script from stdin." << endl;
38 cout << endl;
39 cout << "Usage: ls_instr_script ENGINE [OPTIONS]" << endl;
40 cout << endl;
41 cout << " ENGINE\n";
42 cout << " Either \"core\", \"gig\", \"sf2\" or \"sfz\"." << endl;
43 cout << endl;
44 cout << " OPTIONS" << endl;
45 cout << " --syntax | -s" << endl;
46 cout << " Prints the script to stdout with colored syntax highlighting" << endl;
47 cout << " and exits immediately." << endl;
48 cout << endl;
49 cout << " --debug-syntax | -ds" << endl;
50 cout << " Prints a debugging representation (of the syntax" << endl;
51 cout << " highlighting backend) of the parsed script to stdout and exits" << endl;
52 cout << " immediately." << endl;
53 cout << endl;
54 cout << " --auto-suspend" << endl;
55 cout << " In contrast to the real sampler, this command line program " << endl;
56 cout << " disables automatic suspension by the VM by default to ease " << endl;
57 cout << " i.e. bench marking tasks and the like. By providing this " << endl;
58 cout << " argument auto suspension will be enabled." << endl;
59 cout << endl;
60 cout << "If you pass \"core\" as argument, only the core language built-in" << endl;
61 cout << "variables and functions are available. However in this particular" << endl;
62 cout << "mode the program will not just parse the given script, but also" << endl;
63 cout << "execute the event handlers. All other arguments for ENGINE provide" << endl;
64 cout << "the sampler engine / sampler format specific additional built-in" << endl;
65 cout << "variables and functions, however they wil not be executed by this" << endl;
66 cout << "program." << endl;
67 cout << endl;
68 }
69
70 static void printCodeWithSyntaxHighlighting(ScriptVM* vm);
71 static void dumpSyntaxHighlighting(ScriptVM* vm);
72
73 int main(int argc, char *argv[]) {
74 if (argc < 2) {
75 printUsage();
76 return -1;
77 }
78 String engine = argv[1];
79 bool runScript = false;
80
81 ScriptVM* vm;
82 if (engine == "core") {
83 vm = new ScriptVM;
84 runScript = true;
85 } else if (engine == "sf2" || engine == "sfz") {
86 vm = new InstrumentScriptVM;
87 } else if (engine == "gig") {
88 vm = new gig::InstrumentScriptVM;
89 } else {
90 std::cerr << "Unknown ENGINE '" << engine << "'\n\n";
91 printUsage();
92 return -1;
93 }
94 vm->setAutoSuspendEnabled(false);
95
96 // validate & parse arguments provided to this program
97 for (int iArg = 2; iArg < argc; ++iArg) {
98 const string opt = argv[iArg];
99 if (opt == "--") { // common for all command line tools: separator between initial option arguments and i.e. subsequent file arguments
100 iArg++;
101 break;
102 }
103 if (opt.substr(0, 1) != "-") break;
104
105 if (opt == "-s" || opt == "--syntax") {
106 printCodeWithSyntaxHighlighting(vm);
107 return 0;
108 } else if (opt == "-ds" || opt == "--debug-syntax") {
109 dumpSyntaxHighlighting(vm);
110 return 0;
111 } else if (opt == "--auto-suspend") {
112 vm->setAutoSuspendEnabled(true);
113 } else {
114 cerr << "Unknown option '" << opt << "'" << endl;
115 cerr << endl;
116 printUsage();
117 return -1;
118 }
119 }
120
121 VMParserContext* parserContext = vm->loadScript(&std::cin);
122
123 std::vector<ParserIssue> errors = parserContext->errors();
124 std::vector<ParserIssue> warnings = parserContext->warnings();
125 std::vector<ParserIssue> issues = parserContext->issues();
126 if (warnings.empty() && errors.empty()) {
127 CFmt fmt; fmt.green();
128 printf("EOF. Script parse completed successfully (no errors, no warnings).\n");
129 } else if (!errors.empty()) {
130 CFmt fmt; fmt.red();
131 printf("EOF. Script parse completed with issues (%d errors, %d warnings):\n",
132 int(errors.size()), int(warnings.size()));
133 } else {
134 CFmt fmt; fmt.yellow();
135 printf("EOF. Script parse completed with issues (%d errors, %d warnings):\n",
136 int(errors.size()), int(warnings.size()));
137 }
138 for (int i = 0; i < issues.size(); ++i) {
139 CFmt fmt;
140 if (issues[i].isWrn()) fmt.yellow();
141 else if (issues[i].isErr()) fmt.red();
142 issues[i].dump();
143 }
144
145 printf("[Dumping parsed VM tree]\n");
146 vm->dumpParsedScript(parserContext);
147 printf("[End of parsed VM tree]\n");
148
149 if (!errors.empty()) {
150 if (parserContext) delete parserContext;
151 return -1;
152 }
153
154 if (!runScript) {
155 return 0;
156 }
157
158 if (!parserContext->eventHandler(0)) {
159 printf("No event handler exists. So nothing to execute.\n");
160 if (parserContext) delete parserContext;
161 return 0;
162 }
163
164 printf("Preparing execution of script.\n");
165 VMExecContext* execContext = vm->createExecContext(parserContext);
166 for (int i = 0; parserContext->eventHandler(i); ++i) {
167 VMEventHandler* handler = parserContext->eventHandler(i);
168 printf("[Running event handler '%s']\n", handler->eventHandlerName().c_str());
169 VMExecStatus_t result = vm->exec(parserContext, execContext, handler);
170 CFmt fmt;
171 if (result & VM_EXEC_ERROR) {
172 fmt.red();
173 printf("[Event handler '%s' finished with ERROR status]\n", handler->eventHandlerName().c_str());
174 } else if (result & VM_EXEC_SUSPENDED) {
175 fmt.yellow();
176 printf("[Event handler '%s' returned with SUSPENDED status: %d microseconds]\n",
177 handler->eventHandlerName().c_str(), execContext->suspensionTimeMicroseconds());
178 } else if (!(result & VM_EXEC_RUNNING)) {
179 fmt.green();
180 printf("[Event handler '%s' finished with SUCCESS status]\n", handler->eventHandlerName().c_str());
181 } else if (result & VM_EXEC_RUNNING) {
182 fmt.cyan();
183 printf("[Event handler '%s' finished with RUNNING status]\n", handler->eventHandlerName().c_str());
184 } else {
185 fmt.red();
186 printf("[Event handler '%s' finished with UNKNOWN status]\n", handler->eventHandlerName().c_str());
187 }
188 }
189
190 if (parserContext) delete parserContext;
191 if (execContext) delete execContext;
192 if (vm) delete vm;
193
194 return 0;
195 }
196
197 static void printCodeWithSyntaxHighlighting(ScriptVM* vm) {
198 vector<VMSourceToken> tokens = vm->syntaxHighlighting(&std::cin);
199
200 for (int i = 0; i < tokens.size(); ++i) {
201 const VMSourceToken& token = tokens[i];
202
203 CFmt fmt;
204 if (token.isKeyword()) {
205 fmt.bold();
206 } else if (token.isVariableName()) {
207 fmt.magenta();
208 } else if (token.isIdentifier()) {
209 if (token.isEventHandlerName()) {
210 fmt.bold();
211 fmt.cyan();
212 } else { // a function ...
213 fmt.cyan();
214 }
215 } else if (token.isNumberLiteral()) {
216 fmt.yellow();
217 } else if (token.isStringLiteral()) {
218 fmt.red();
219 } else if (token.isComment()) {
220 fmt.blue();
221 } else if (token.isPreprocessor()) {
222 fmt.green();
223 } else if (token.isNewLine()) {
224 }
225
226 printf("%s", token.text().c_str());
227 fflush(stdout);
228 }
229 }
230
231 static void dumpSyntaxHighlighting(ScriptVM* vm) {
232 vector<VMSourceToken> tokens = vm->syntaxHighlighting(&std::cin);
233
234 for (int i = 0; i < tokens.size(); ++i) {
235 const VMSourceToken& token = tokens[i];
236 const char* type = "OTHER";
237 if (token.isKeyword()) {
238 type = "KEYWORD";
239 } else if (token.isVariableName()) {
240 type = "VARIABLE";
241 } else if (token.isIdentifier()) {
242 if (token.isEventHandlerName()) {
243 type = "HANDLER_NAME";
244 } else { // a function ...
245 type = "FUNCTION";
246 }
247 } else if (token.isNumberLiteral()) {
248 type = "NUMBER";
249 } else if (token.isStringLiteral()) {
250 type = "STRING";
251 } else if (token.isComment()) {
252 type = "COMMENT";
253 } else if (token.isPreprocessor()) {
254 type = "PREPROC";
255 } else if (token.isNewLine()) {
256 type = "NL";
257 }
258 printf("L%d,C%d: %s \"%s\"\n", token.firstLine(), token.firstColumn(), type, token.text().c_str());
259 }
260 }

  ViewVC Help
Powered by ViewVC