/[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 2974 - (hide 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 schoenebeck 2581 /*
2 schoenebeck 2885 * Copyright (c) 2014-2016 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 2581
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 schoenebeck 2611 ls_instr_script core < src/scriptvm/examples/helloworld.txt
23 schoenebeck 2581
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 schoenebeck 2611 using namespace std;
35 schoenebeck 2581
36 schoenebeck 2611 static void printUsage() {
37     cout << "ls_instr_script - Parse real-time instrument script from stdin." << endl;
38     cout << endl;
39 schoenebeck 2885 cout << "Usage: ls_instr_script ENGINE [OPTIONS]" << endl;
40 schoenebeck 2611 cout << endl;
41     cout << " ENGINE\n";
42     cout << " Either \"core\", \"gig\", \"sf2\" or \"sfz\"." << endl;
43     cout << endl;
44 schoenebeck 2885 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 schoenebeck 2974 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 schoenebeck 2611 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 schoenebeck 2581
70 schoenebeck 2885 static void printCodeWithSyntaxHighlighting(ScriptVM* vm);
71     static void dumpSyntaxHighlighting(ScriptVM* vm);
72    
73 schoenebeck 2611 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 schoenebeck 2974 vm->setAutoSuspendEnabled(false);
95 schoenebeck 2611
96 schoenebeck 2885 // 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 schoenebeck 2974 } else if (opt == "--auto-suspend") {
112     vm->setAutoSuspendEnabled(true);
113 schoenebeck 2885 } else {
114     cerr << "Unknown option '" << opt << "'" << endl;
115     cerr << endl;
116     printUsage();
117     return -1;
118     }
119     }
120    
121 schoenebeck 2611 VMParserContext* parserContext = vm->loadScript(&std::cin);
122    
123 schoenebeck 2588 std::vector<ParserIssue> errors = parserContext->errors();
124     std::vector<ParserIssue> warnings = parserContext->warnings();
125     std::vector<ParserIssue> issues = parserContext->issues();
126 schoenebeck 2581 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 persson 2837 int(errors.size()), int(warnings.size()));
133 schoenebeck 2581 } else {
134     CFmt fmt; fmt.yellow();
135     printf("EOF. Script parse completed with issues (%d errors, %d warnings):\n",
136 persson 2837 int(errors.size()), int(warnings.size()));
137 schoenebeck 2581 }
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 schoenebeck 2611 vm->dumpParsedScript(parserContext);
147 schoenebeck 2581 printf("[End of parsed VM tree]\n");
148    
149 schoenebeck 2588 if (!errors.empty()) {
150     if (parserContext) delete parserContext;
151     return -1;
152     }
153 schoenebeck 2581
154 schoenebeck 2611 if (!runScript) {
155     return 0;
156     }
157    
158 schoenebeck 2588 if (!parserContext->eventHandler(0)) {
159 schoenebeck 2581 printf("No event handler exists. So nothing to execute.\n");
160 schoenebeck 2588 if (parserContext) delete parserContext;
161 schoenebeck 2581 return 0;
162     }
163    
164     printf("Preparing execution of script.\n");
165 schoenebeck 2611 VMExecContext* execContext = vm->createExecContext(parserContext);
166 schoenebeck 2588 for (int i = 0; parserContext->eventHandler(i); ++i) {
167     VMEventHandler* handler = parserContext->eventHandler(i);
168 schoenebeck 2581 printf("[Running event handler '%s']\n", handler->eventHandlerName().c_str());
169 schoenebeck 2611 VMExecStatus_t result = vm->exec(parserContext, execContext, handler);
170 schoenebeck 2581 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 schoenebeck 2588 handler->eventHandlerName().c_str(), execContext->suspensionTimeMicroseconds());
178 schoenebeck 2581 } 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 schoenebeck 2611
190 schoenebeck 2588 if (parserContext) delete parserContext;
191     if (execContext) delete execContext;
192 schoenebeck 2611 if (vm) delete vm;
193 schoenebeck 2581
194     return 0;
195     }
196 schoenebeck 2885
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