/[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 3707 - (show annotations) (download)
Wed Jan 8 21:21:58 2020 UTC (4 years, 3 months ago) by schoenebeck
File size: 10395 byte(s)
Fixed compiler warnings about format specifiers:

Use portable format specifiers like PRId64 from inttypes.h
instead of assuming a particular word size.

1 /*
2 * Copyright (c) 2014-2020 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: %" PRId64 " microseconds]\n",
192 handler->eventHandlerName().c_str(),
193 (int64_t)execContext->suspensionTimeMicroseconds());
194 } else if (!(result & VM_EXEC_RUNNING)) {
195 fmt.green();
196 printf("[Event handler '%s' finished with SUCCESS status]\n", handler->eventHandlerName().c_str());
197 } else if (result & VM_EXEC_RUNNING) {
198 fmt.cyan();
199 printf("[Event handler '%s' finished with RUNNING status]\n", handler->eventHandlerName().c_str());
200 } else {
201 fmt.red();
202 printf("[Event handler '%s' finished with UNKNOWN status]\n", handler->eventHandlerName().c_str());
203 }
204 }
205
206 if (parserContext) delete parserContext;
207 if (execContext) delete execContext;
208 if (vm) delete vm;
209
210 return 0;
211 }
212
213 static void printCodeWithSyntaxHighlighting(ScriptVM* vm) {
214 vector<VMSourceToken> tokens = vm->syntaxHighlighting(&std::cin);
215
216 for (int i = 0; i < tokens.size(); ++i) {
217 const VMSourceToken& token = tokens[i];
218
219 CFmt fmt;
220 if (token.isKeyword()) {
221 fmt.bold();
222 } else if (token.isVariableName()) {
223 fmt.magenta();
224 } else if (token.isIdentifier()) {
225 if (token.isEventHandlerName()) {
226 fmt.bold();
227 fmt.cyan();
228 } else { // a function ...
229 fmt.cyan();
230 }
231 } else if (token.isNumberLiteral()) {
232 fmt.yellow();
233 } else if (token.isStringLiteral()) {
234 fmt.red();
235 } else if (token.isComment()) {
236 fmt.blue();
237 } else if (token.isPreprocessor()) {
238 fmt.green();
239 } else if (token.isNewLine()) {
240 }
241
242 printf("%s", token.text().c_str());
243 fflush(stdout);
244 }
245 }
246
247 static void dumpSyntaxHighlighting(ScriptVM* vm) {
248 vector<VMSourceToken> tokens = vm->syntaxHighlighting(&std::cin);
249
250 for (int i = 0; i < tokens.size(); ++i) {
251 const VMSourceToken& token = tokens[i];
252 const char* type = "OTHER";
253 if (token.isKeyword()) {
254 type = "KEYWORD";
255 } else if (token.isVariableName()) {
256 type = "VARIABLE";
257 } else if (token.isIdentifier()) {
258 if (token.isEventHandlerName()) {
259 type = "HANDLER_NAME";
260 } else { // a function ...
261 type = "FUNCTION";
262 }
263 } else if (token.isNumberLiteral()) {
264 type = "NUMBER";
265 } else if (token.isStringLiteral()) {
266 type = "STRING";
267 } else if (token.isComment()) {
268 type = "COMMENT";
269 } else if (token.isPreprocessor()) {
270 type = "PREPROC";
271 } else if (token.isNewLine()) {
272 type = "NL";
273 }
274 printf("L%d,C%d: %s \"%s\"\n", token.firstLine(), token.firstColumn(), type, token.text().c_str());
275 }
276 }
277
278 static String readTxtFromFile(String path) {
279 std::ifstream f(path.c_str(), std::ifstream::in);
280 String s;
281 s += (char) f.get();
282 while (f.good()) {
283 char c = f.get();
284 if (c == EOF) break;
285 s += c;
286 }
287 f.close();
288 return s;
289 }

  ViewVC Help
Powered by ViewVC