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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3707 - (hide annotations) (download)
Wed Jan 8 21:21:58 2020 UTC (4 years, 2 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 schoenebeck 2581 /*
2 schoenebeck 3707 * Copyright (c) 2014-2020 Christian Schoenebeck
3 schoenebeck 2581 *
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 schoenebeck 2611 #include "engines/common/InstrumentScriptVM.h"
14     #include "engines/gig/InstrumentScriptVM.h"
15     #include <iostream>
16 schoenebeck 3308 #include <fstream>
17 schoenebeck 2581
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 schoenebeck 2611 ls_instr_script core < src/scriptvm/examples/helloworld.txt
24 schoenebeck 2581
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 schoenebeck 2611 using namespace std;
36 schoenebeck 2581
37 schoenebeck 2611 static void printUsage() {
38     cout << "ls_instr_script - Parse real-time instrument script from stdin." << endl;
39     cout << endl;
40 schoenebeck 2885 cout << "Usage: ls_instr_script ENGINE [OPTIONS]" << endl;
41 schoenebeck 2611 cout << endl;
42     cout << " ENGINE\n";
43     cout << " Either \"core\", \"gig\", \"sf2\" or \"sfz\"." << endl;
44     cout << endl;
45 schoenebeck 2885 cout << " OPTIONS" << endl;
46 schoenebeck 3308 cout << " --file FILE | -f FILE" << endl;
47     cout << " Read from this file instead from stdin." << endl;
48     cout << endl;
49 schoenebeck 2885 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 schoenebeck 2974 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 schoenebeck 2611 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 schoenebeck 2581
74 schoenebeck 2885 static void printCodeWithSyntaxHighlighting(ScriptVM* vm);
75     static void dumpSyntaxHighlighting(ScriptVM* vm);
76 schoenebeck 3308 static String readTxtFromFile(String path);
77 schoenebeck 2885
78 schoenebeck 2611 int main(int argc, char *argv[]) {
79     if (argc < 2) {
80     printUsage();
81     return -1;
82     }
83     String engine = argv[1];
84 schoenebeck 3308 String path;
85 schoenebeck 2611 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 schoenebeck 2974 vm->setAutoSuspendEnabled(false);
101 schoenebeck 2611
102 schoenebeck 2885 // 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 schoenebeck 2974 } else if (opt == "--auto-suspend") {
118     vm->setAutoSuspendEnabled(true);
119 schoenebeck 3308 } else if (opt == "-f" || opt == "--file") {
120     if (++iArg < argc)
121     path = argv[iArg];
122 schoenebeck 2885 } else {
123     cerr << "Unknown option '" << opt << "'" << endl;
124     cerr << endl;
125     printUsage();
126     return -1;
127     }
128     }
129    
130 schoenebeck 3308 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 schoenebeck 2611
138 schoenebeck 2588 std::vector<ParserIssue> errors = parserContext->errors();
139     std::vector<ParserIssue> warnings = parserContext->warnings();
140     std::vector<ParserIssue> issues = parserContext->issues();
141 schoenebeck 2581 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 persson 2837 int(errors.size()), int(warnings.size()));
148 schoenebeck 2581 } else {
149     CFmt fmt; fmt.yellow();
150     printf("EOF. Script parse completed with issues (%d errors, %d warnings):\n",
151 persson 2837 int(errors.size()), int(warnings.size()));
152 schoenebeck 2581 }
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 schoenebeck 2611 vm->dumpParsedScript(parserContext);
162 schoenebeck 2581 printf("[End of parsed VM tree]\n");
163    
164 schoenebeck 2588 if (!errors.empty()) {
165     if (parserContext) delete parserContext;
166     return -1;
167     }
168 schoenebeck 2581
169 schoenebeck 2611 if (!runScript) {
170     return 0;
171     }
172    
173 schoenebeck 2588 if (!parserContext->eventHandler(0)) {
174 schoenebeck 2581 printf("No event handler exists. So nothing to execute.\n");
175 schoenebeck 2588 if (parserContext) delete parserContext;
176 schoenebeck 2581 return 0;
177     }
178    
179     printf("Preparing execution of script.\n");
180 schoenebeck 2611 VMExecContext* execContext = vm->createExecContext(parserContext);
181 schoenebeck 2588 for (int i = 0; parserContext->eventHandler(i); ++i) {
182     VMEventHandler* handler = parserContext->eventHandler(i);
183 schoenebeck 2581 printf("[Running event handler '%s']\n", handler->eventHandlerName().c_str());
184 schoenebeck 2611 VMExecStatus_t result = vm->exec(parserContext, execContext, handler);
185 schoenebeck 2581 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 schoenebeck 3707 printf("[Event handler '%s' returned with SUSPENDED status: %" PRId64 " microseconds]\n",
192     handler->eventHandlerName().c_str(),
193     (int64_t)execContext->suspensionTimeMicroseconds());
194 schoenebeck 2581 } 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 schoenebeck 2611
206 schoenebeck 2588 if (parserContext) delete parserContext;
207     if (execContext) delete execContext;
208 schoenebeck 2611 if (vm) delete vm;
209 schoenebeck 2581
210     return 0;
211     }
212 schoenebeck 2885
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 schoenebeck 3308
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