/[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 3308 - (hide annotations) (download)
Sat Jul 15 01:14:20 2017 UTC (6 years, 10 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 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 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     printf("[Event handler '%s' returned with SUSPENDED status: %d microseconds]\n",
192 schoenebeck 2588 handler->eventHandlerName().c_str(), execContext->suspensionTimeMicroseconds());
193 schoenebeck 2581 } 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 schoenebeck 2611
205 schoenebeck 2588 if (parserContext) delete parserContext;
206     if (execContext) delete execContext;
207 schoenebeck 2611 if (vm) delete vm;
208 schoenebeck 2581
209     return 0;
210     }
211 schoenebeck 2885
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 schoenebeck 3308
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