/[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 2885 - (hide annotations) (download)
Fri Apr 22 15:37:45 2016 UTC (7 years, 11 months ago) by schoenebeck
File size: 9039 byte(s)
* Instrument script classes now exported with the liblinuxsampler C++ API.
* Added new API method ScriptVM::syntaxHighlighting() which provides
  a convenient syntax highlighting backend for external instrument
  script editor applications.
* Bumped version (2.0.0.svn5).

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 2611 cout << "If you pass \"core\" as argument, only the core language built-in" << endl;
55     cout << "variables and functions are available. However in this particular" << endl;
56     cout << "mode the program will not just parse the given script, but also" << endl;
57     cout << "execute the event handlers. All other arguments for ENGINE provide" << endl;
58     cout << "the sampler engine / sampler format specific additional built-in" << endl;
59     cout << "variables and functions, however they wil not be executed by this" << endl;
60     cout << "program." << endl;
61     cout << endl;
62     }
63 schoenebeck 2581
64 schoenebeck 2885 static void printCodeWithSyntaxHighlighting(ScriptVM* vm);
65     static void dumpSyntaxHighlighting(ScriptVM* vm);
66    
67 schoenebeck 2611 int main(int argc, char *argv[]) {
68     if (argc < 2) {
69     printUsage();
70     return -1;
71     }
72     String engine = argv[1];
73     bool runScript = false;
74    
75     ScriptVM* vm;
76     if (engine == "core") {
77     vm = new ScriptVM;
78     runScript = true;
79     } else if (engine == "sf2" || engine == "sfz") {
80     vm = new InstrumentScriptVM;
81     } else if (engine == "gig") {
82     vm = new gig::InstrumentScriptVM;
83     } else {
84     std::cerr << "Unknown ENGINE '" << engine << "'\n\n";
85     printUsage();
86     return -1;
87     }
88    
89 schoenebeck 2885 // validate & parse arguments provided to this program
90     for (int iArg = 2; iArg < argc; ++iArg) {
91     const string opt = argv[iArg];
92     if (opt == "--") { // common for all command line tools: separator between initial option arguments and i.e. subsequent file arguments
93     iArg++;
94     break;
95     }
96     if (opt.substr(0, 1) != "-") break;
97    
98     if (opt == "-s" || opt == "--syntax") {
99     printCodeWithSyntaxHighlighting(vm);
100     return 0;
101     } else if (opt == "-ds" || opt == "--debug-syntax") {
102     dumpSyntaxHighlighting(vm);
103     return 0;
104     } else {
105     cerr << "Unknown option '" << opt << "'" << endl;
106     cerr << endl;
107     printUsage();
108     return -1;
109     }
110     }
111    
112 schoenebeck 2611 VMParserContext* parserContext = vm->loadScript(&std::cin);
113    
114 schoenebeck 2588 std::vector<ParserIssue> errors = parserContext->errors();
115     std::vector<ParserIssue> warnings = parserContext->warnings();
116     std::vector<ParserIssue> issues = parserContext->issues();
117 schoenebeck 2581 if (warnings.empty() && errors.empty()) {
118     CFmt fmt; fmt.green();
119     printf("EOF. Script parse completed successfully (no errors, no warnings).\n");
120     } else if (!errors.empty()) {
121     CFmt fmt; fmt.red();
122     printf("EOF. Script parse completed with issues (%d errors, %d warnings):\n",
123 persson 2837 int(errors.size()), int(warnings.size()));
124 schoenebeck 2581 } else {
125     CFmt fmt; fmt.yellow();
126     printf("EOF. Script parse completed with issues (%d errors, %d warnings):\n",
127 persson 2837 int(errors.size()), int(warnings.size()));
128 schoenebeck 2581 }
129     for (int i = 0; i < issues.size(); ++i) {
130     CFmt fmt;
131     if (issues[i].isWrn()) fmt.yellow();
132     else if (issues[i].isErr()) fmt.red();
133     issues[i].dump();
134     }
135    
136     printf("[Dumping parsed VM tree]\n");
137 schoenebeck 2611 vm->dumpParsedScript(parserContext);
138 schoenebeck 2581 printf("[End of parsed VM tree]\n");
139    
140 schoenebeck 2588 if (!errors.empty()) {
141     if (parserContext) delete parserContext;
142     return -1;
143     }
144 schoenebeck 2581
145 schoenebeck 2611 if (!runScript) {
146     return 0;
147     }
148    
149 schoenebeck 2588 if (!parserContext->eventHandler(0)) {
150 schoenebeck 2581 printf("No event handler exists. So nothing to execute.\n");
151 schoenebeck 2588 if (parserContext) delete parserContext;
152 schoenebeck 2581 return 0;
153     }
154    
155     printf("Preparing execution of script.\n");
156 schoenebeck 2611 VMExecContext* execContext = vm->createExecContext(parserContext);
157 schoenebeck 2588 for (int i = 0; parserContext->eventHandler(i); ++i) {
158     VMEventHandler* handler = parserContext->eventHandler(i);
159 schoenebeck 2581 printf("[Running event handler '%s']\n", handler->eventHandlerName().c_str());
160 schoenebeck 2611 VMExecStatus_t result = vm->exec(parserContext, execContext, handler);
161 schoenebeck 2581 CFmt fmt;
162     if (result & VM_EXEC_ERROR) {
163     fmt.red();
164     printf("[Event handler '%s' finished with ERROR status]\n", handler->eventHandlerName().c_str());
165     } else if (result & VM_EXEC_SUSPENDED) {
166     fmt.yellow();
167     printf("[Event handler '%s' returned with SUSPENDED status: %d microseconds]\n",
168 schoenebeck 2588 handler->eventHandlerName().c_str(), execContext->suspensionTimeMicroseconds());
169 schoenebeck 2581 } else if (!(result & VM_EXEC_RUNNING)) {
170     fmt.green();
171     printf("[Event handler '%s' finished with SUCCESS status]\n", handler->eventHandlerName().c_str());
172     } else if (result & VM_EXEC_RUNNING) {
173     fmt.cyan();
174     printf("[Event handler '%s' finished with RUNNING status]\n", handler->eventHandlerName().c_str());
175     } else {
176     fmt.red();
177     printf("[Event handler '%s' finished with UNKNOWN status]\n", handler->eventHandlerName().c_str());
178     }
179     }
180 schoenebeck 2611
181 schoenebeck 2588 if (parserContext) delete parserContext;
182     if (execContext) delete execContext;
183 schoenebeck 2611 if (vm) delete vm;
184 schoenebeck 2581
185     return 0;
186     }
187 schoenebeck 2885
188     static void printCodeWithSyntaxHighlighting(ScriptVM* vm) {
189     vector<VMSourceToken> tokens = vm->syntaxHighlighting(&std::cin);
190    
191     for (int i = 0; i < tokens.size(); ++i) {
192     const VMSourceToken& token = tokens[i];
193    
194     CFmt fmt;
195     if (token.isKeyword()) {
196     fmt.bold();
197     } else if (token.isVariableName()) {
198     fmt.magenta();
199     } else if (token.isIdentifier()) {
200     if (token.isEventHandlerName()) {
201     fmt.bold();
202     fmt.cyan();
203     } else { // a function ...
204     fmt.cyan();
205     }
206     } else if (token.isNumberLiteral()) {
207     fmt.yellow();
208     } else if (token.isStringLiteral()) {
209     fmt.red();
210     } else if (token.isComment()) {
211     fmt.blue();
212     } else if (token.isPreprocessor()) {
213     fmt.green();
214     } else if (token.isNewLine()) {
215     }
216    
217     printf("%s", token.text().c_str());
218     fflush(stdout);
219     }
220     }
221    
222     static void dumpSyntaxHighlighting(ScriptVM* vm) {
223     vector<VMSourceToken> tokens = vm->syntaxHighlighting(&std::cin);
224    
225     for (int i = 0; i < tokens.size(); ++i) {
226     const VMSourceToken& token = tokens[i];
227     const char* type = "OTHER";
228     if (token.isKeyword()) {
229     type = "KEYWORD";
230     } else if (token.isVariableName()) {
231     type = "VARIABLE";
232     } else if (token.isIdentifier()) {
233     if (token.isEventHandlerName()) {
234     type = "HANDLER_NAME";
235     } else { // a function ...
236     type = "FUNCTION";
237     }
238     } else if (token.isNumberLiteral()) {
239     type = "NUMBER";
240     } else if (token.isStringLiteral()) {
241     type = "STRING";
242     } else if (token.isComment()) {
243     type = "COMMENT";
244     } else if (token.isPreprocessor()) {
245     type = "PREPROC";
246     } else if (token.isNewLine()) {
247     type = "NL";
248     }
249     printf("L%d,C%d: %s \"%s\"\n", token.firstLine(), token.firstColumn(), type, token.text().c_str());
250     }
251     }

  ViewVC Help
Powered by ViewVC