/[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 3308 - (show annotations) (download)
Sat Jul 15 01:14:20 2017 UTC (6 years, 9 months ago) by schoenebeck
File size: 10358 byte(s)
* NKSP script editor API: Fixed app termination due to a lexer start
  condition stack underrun.
* NKSP preprocessor: Fixed wrong behavior on nested USE_CODE_IF() and
  USE_CODE_IF_NOT() preprocessor statements.
* Bumped version (2.0.0.svn70).

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

  ViewVC Help
Powered by ViewVC