1 /************************************************************************
2 ************************************************************************
3 FAUST compiler
4 Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
21
22 #ifdef WIN32
23 #pragma warning(disable : 4996 4146 4244)
24 #endif
25
26 #include <limits.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <cstdlib>
30 #include <fstream>
31 #include <iostream>
32 #include <list>
33 #include <sstream>
34 #include <string>
35 #include <vector>
36
37 #include "Text.hh"
38 #include "compatibility.hh"
39 #include "dag_instructions_compiler.hh"
40 #include "description.hh"
41 #include "doc.hh"
42 #include "drawschema.hh"
43 #include "enrobage.hh"
44 #include "errormsg.hh"
45 #include "eval.hh"
46 #include "exception.hh"
47 #include "exepath.hh"
48 #include "floats.hh"
49 #include "garbageable.hh"
50 #include "global.hh"
51 #include "instructions_compiler.hh"
52 #include "instructions_compiler1.hh"
53 #include "libfaust.h"
54 #include "ppbox.hh"
55 #include "ppsig.hh"
56 #include "privatise.hh"
57 #include "propagate.hh"
58 #include "recursivness.hh"
59 #include "schema.h"
60 #include "signals.hh"
61 #include "sigprint.hh"
62 #include "sigtype.hh"
63 #include "sigtyperules.hh"
64 #include "simplify.hh"
65 #include "sourcereader.hh"
66 #include "timing.hh"
67 #include "labels.hh"
68 #include "xtended.hh"
69
70 #ifdef C_BUILD
71 #include "c_code_container.hh"
72 #endif
73
74 #ifdef CPP_BUILD
75 #include "cpp_code_container.hh"
76 #include "cpp_gpu_code_container.hh"
77 #endif
78
79 #ifdef CSHARP_BUILD
80 #include "csharp_code_container.hh"
81 #endif
82
83 #ifdef DLANG_BUILD
84 #include "dlang_code_container.hh"
85 #endif
86
87 #ifdef FIR_BUILD
88 #include "fir_code_container.hh"
89 #endif
90
91 #ifdef INTERP_BUILD
92 #include "interpreter_code_container.cpp"
93 #endif
94
95 #ifdef JAVA_BUILD
96 #include "java_code_container.hh"
97 #endif
98
99 #ifdef JULIA_BUILD
100 #include "julia_code_container.hh"
101 #endif
102
103 #ifdef LLVM_BUILD
104 #include "clang_code_container.hh"
105 #include "llvm_code_container.hh"
106 #endif
107
108 #ifdef OCPP_BUILD
109 #include "compile_scal.hh"
110 #include "compile_sched.hh"
111 #include "compile_vect.hh"
112 #endif
113
114 #ifdef RUST_BUILD
115 #include "rust_code_container.hh"
116 #endif
117
118 #ifdef SOUL_BUILD
119 #include "soul_code_container.hh"
120 #endif
121
122 #ifdef WASM_BUILD
123 #include "wasm_code_container.hh"
124 #include "wast_code_container.hh"
125 #endif
126
127 using namespace std;
128
129 static unique_ptr<ifstream> injcode;
130 static unique_ptr<ifstream> enrobage;
131
132 unique_ptr<ostream> helpers;
133
134 #ifdef OCPP_BUILD
135 // Old CPP compiler
136 Compiler* old_comp = nullptr;
137 #endif
138
139 // FIR container
140 InstructionsCompiler* new_comp = nullptr;
141 CodeContainer* container = nullptr;
142
143 typedef void* (*compile_fun)(void* arg);
144
145 string reorganizeCompilationOptions(int argc, const char* argv[]);
146
enumBackends(ostream & out)147 static void enumBackends(ostream& out)
148 {
149 const char* dspto = " DSP to ";
150 #ifdef C_BUILD
151 out << dspto << "C" << endl;
152 #endif
153
154 #ifdef CPP_BUILD
155 out << dspto << "C++" << endl;
156 #endif
157
158 #ifdef CSHARP_BUILD
159 out << dspto << "CSharp" << endl;
160 #endif
161
162 #ifdef DLANG_BUILD
163 out << dspto << "DLang" << endl;
164 #endif
165
166 #ifdef FIR_BUILD
167 out << dspto << "FIR" << endl;
168 #endif
169
170 #ifdef INTERP_BUILD
171 out << dspto << "Interpreter" << endl;
172 #endif
173
174 #ifdef JAVA_BUILD
175 out << dspto << "Java" << endl;
176 #endif
177
178 #ifdef JULIA_BUILD
179 out << dspto << "Julia" << endl;
180 #endif
181
182 #ifdef LLVM_BUILD
183 out << dspto << "LLVM IR" << endl;
184 #endif
185
186 #ifdef OCPP_BUILD
187 out << dspto << "old C++" << endl;
188 #endif
189
190 #ifdef RUST_BUILD
191 out << dspto << "Rust" << endl;
192 #endif
193
194 #ifdef SOUL_BUILD
195 out << dspto << "SOUL" << endl;
196 #endif
197
198 #ifdef WASM_BUILD
199 out << dspto << "WebAssembly (wast/wasm)" << endl;
200 #endif
201 }
202
callFun(compile_fun fun)203 static void callFun(compile_fun fun)
204 {
205 #if defined(EMCC)
206 // No thread support in JS or WIN32
207 fun(NULL);
208 #elif defined(_WIN32)
209 DWORD id;
210 HANDLE thread = CreateThread(NULL, MAX_STACK_SIZE, LPTHREAD_START_ROUTINE(fun), NULL, 0, &id);
211 faustassert(thread != NULL);
212 WaitForSingleObject(thread, INFINITE);
213 #else
214 pthread_t thread;
215 pthread_attr_t attr;
216 faustassert(pthread_attr_init(&attr) == 0);
217 faustassert(pthread_attr_setstacksize(&attr, MAX_STACK_SIZE) == 0);
218 faustassert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) == 0);
219 faustassert(pthread_create(&thread, &attr, fun, nullptr) == 0);
220 pthread_join(thread, nullptr);
221 #endif
222 }
223
224 static Tree evaluateBlockDiagram(Tree expandedDefList, int& numInputs, int& numOutputs);
225
threadEvaluateBlockDiagram(void * arg)226 static void* threadEvaluateBlockDiagram(void* arg)
227 {
228 try {
229 gGlobal->gProcessTree =
230 evaluateBlockDiagram(gGlobal->gExpandedDefList, gGlobal->gNumInputs, gGlobal->gNumOutputs);
231 } catch (faustexception& e) {
232 gGlobal->gErrorMessage = e.Message();
233 }
234 return 0;
235 }
236
threadBoxPropagateSig(void * arg)237 static void* threadBoxPropagateSig(void* arg)
238 {
239 try {
240 gGlobal->gLsignalsTree =
241 boxPropagateSig(gGlobal->nil, gGlobal->gProcessTree, makeSigInputList(gGlobal->gNumInputs));
242 } catch (faustexception& e) {
243 gGlobal->gErrorMessage = e.Message();
244 }
245 return 0;
246 }
247
248 /****************************************************************
249 Global context variable
250 *****************************************************************/
251
252 global* gGlobal = nullptr;
253
254 // Timing can be used outside of the scope of 'gGlobal'
255 extern bool gTimingSwitch;
256
257 /****************************************************************
258 Parser variables
259 *****************************************************************/
260
261 int yyerr;
262
263 /****************************************************************
264 Command line tools and arguments
265 *****************************************************************/
266
267 //-- command line tools
268
isCmd(const char * cmd,const char * kw1)269 static bool isCmd(const char* cmd, const char* kw1)
270 {
271 return (strcmp(cmd, kw1) == 0);
272 }
273
isCmd(const char * cmd,const char * kw1,const char * kw2)274 static bool isCmd(const char* cmd, const char* kw1, const char* kw2)
275 {
276 return (strcmp(cmd, kw1) == 0) || (strcmp(cmd, kw2) == 0);
277 }
278
processCmdline(int argc,const char * argv[])279 static bool processCmdline(int argc, const char* argv[])
280 {
281 int i = 1;
282 int err = 0;
283 stringstream parse_error;
284 bool float_size = false;
285
286 /*
287 for (int i = 0; i < argc; i++) {
288 cout << "processCmdline i = " << i << " cmd = " << argv[i] << "\n";
289 }
290 */
291
292 while (i < argc) {
293 if (isCmd(argv[i], "-h", "--help")) {
294 gGlobal->gHelpSwitch = true;
295 i += 1;
296
297 } else if (isCmd(argv[i], "-lang", "--language") && (i + 1 < argc)) {
298 gGlobal->gOutputLang = argv[i + 1];
299 i += 2;
300
301 } else if (isCmd(argv[i], "-v", "--version")) {
302 gGlobal->gVersionSwitch = true;
303 i += 1;
304
305 } else if (isCmd(argv[i], "-libdir", "--libdir")) {
306 gGlobal->gLibDirSwitch = true;
307 i += 1;
308
309 } else if (isCmd(argv[i], "-includedir", "--includedir")) {
310 gGlobal->gIncludeDirSwitch = true;
311 i += 1;
312
313 } else if (isCmd(argv[i], "-archdir", "--archdir")) {
314 gGlobal->gArchDirSwitch = true;
315 i += 1;
316
317 } else if (isCmd(argv[i], "-dspdir", "--dspdir")) {
318 gGlobal->gDspDirSwitch = true;
319 i += 1;
320
321 } else if (isCmd(argv[i], "-pathslist", "--pathslist")) {
322 gGlobal->gPathListSwitch = true;
323 i += 1;
324
325 } else if (isCmd(argv[i], "-d", "--details")) {
326 gGlobal->gDetailsSwitch = true;
327 i += 1;
328
329 } else if (isCmd(argv[i], "-a", "--architecture") && (i + 1 < argc)) {
330 gGlobal->gArchFile = argv[i + 1];
331 i += 2;
332
333 } else if (isCmd(argv[i], "-inj", "--inject") && (i + 1 < argc)) {
334 gGlobal->gInjectFlag = true;
335 gGlobal->gInjectFile = argv[i + 1];
336 i += 2;
337
338 } else if (isCmd(argv[i], "-o") && (i + 1 < argc)) {
339 gGlobal->gOutputFile = argv[i + 1];
340 i += 2;
341
342 } else if (isCmd(argv[i], "-wi", "--widening-iterations") && (i + 1 < argc)) {
343 gGlobal->gWideningLimit = std::atoi(argv[i+1]);
344 i += 2;
345
346 } else if (isCmd(argv[i], "-ni", "--narrowing-iterations") && (i + 1 < argc)){
347 gGlobal->gNarrowingLimit = std::atoi(argv[i+1]);
348 i += 2;
349
350 } else if (isCmd(argv[i], "-ps", "--postscript")) {
351 gGlobal->gDrawPSSwitch = true;
352 i += 1;
353
354 } else if (isCmd(argv[i], "-xml", "--xml")) {
355 gGlobal->gPrintXMLSwitch = true;
356 i += 1;
357
358 } else if (isCmd(argv[i], "-json", "--json")) {
359 gGlobal->gPrintJSONSwitch = true;
360 i += 1;
361
362 } else if (isCmd(argv[i], "-tg", "--task-graph")) {
363 gGlobal->gGraphSwitch = true;
364 i += 1;
365
366 } else if (isCmd(argv[i], "-sg", "--signal-graph")) {
367 gGlobal->gDrawSignals = true;
368 i += 1;
369
370 } else if (isCmd(argv[i], "-drf", "--draw-route-frame")) {
371 gGlobal->gDrawRouteFrame = true;
372 i += 1;
373
374 } else if (isCmd(argv[i], "-blur", "--shadow-blur")) {
375 gGlobal->gShadowBlur = true;
376 i += 1;
377
378 } else if (isCmd(argv[i], "-sc", "--scaled-svg")) {
379 gGlobal->gScaledSVG = true;
380 i += 1;
381
382 } else if (isCmd(argv[i], "-svg", "--svg")) {
383 gGlobal->gDrawSVGSwitch = true;
384 i += 1;
385
386 } else if (isCmd(argv[i], "-vhdl", "--vhdl")) {
387 gGlobal->gVHDLSwitch = true;
388 i += 1;
389
390 } else if (isCmd(argv[i], "-trace", "--trace")) {
391 gGlobal->gVHDLTrace = true;
392 i += 1;
393
394 } else if (isCmd(argv[i], "-elm", "--elementary")) {
395 gGlobal->gElementarySwitch = true;
396 i += 1;
397
398 } else if (isCmd(argv[i], "-f", "--fold") && (i + 1 < argc)) {
399 gGlobal->gFoldThreshold = std::atoi(argv[i + 1]);
400 i += 2;
401
402 } else if (isCmd(argv[i], "-fc", "--fold-complexity") && (i + 1 < argc)) {
403 gGlobal->gFoldComplexity = std::atoi(argv[i + 1]);
404 i += 2;
405
406 } else if (isCmd(argv[i], "-mns", "--max-name-size") && (i + 1 < argc)) {
407 gGlobal->gMaxNameSize = std::atoi(argv[i + 1]);
408 i += 2;
409
410 } else if (isCmd(argv[i], "-sn", "--simple-names")) {
411 gGlobal->gSimpleNames = true;
412 i += 1;
413
414 } else if (isCmd(argv[i], "-mcd", "--max-copy-delay") && (i + 1 < argc)) {
415 gGlobal->gMaxCopyDelay = std::atoi(argv[i + 1]);
416 i += 2;
417
418 } else if (isCmd(argv[i], "-dlt", "-delay-line-threshold") && (i + 1 < argc)) {
419 gGlobal->gMaskDelayLineThreshold = std::atoi(argv[i + 1]);
420 i += 2;
421
422 } else if (isCmd(argv[i], "-mem", "--memory-manager")) {
423 gGlobal->gMemoryManager = true;
424 i += 1;
425
426 } else if (isCmd(argv[i], "-sd", "--simplify-diagrams")) {
427 gGlobal->gSimplifyDiagrams = true;
428 i += 1;
429
430 } else if (isCmd(argv[i], "-vec", "--vectorize")) {
431 gGlobal->gVectorSwitch = true;
432 i += 1;
433
434 } else if (isCmd(argv[i], "-scal", "--scalar")) {
435 gGlobal->gVectorSwitch = false;
436 i += 1;
437
438 } else if (isCmd(argv[i], "-dfs", "--deepFirstScheduling")) {
439 gGlobal->gDeepFirstSwitch = true;
440 i += 1;
441
442 } else if (isCmd(argv[i], "-vs", "--vec-size") && (i + 1 < argc)) {
443 gGlobal->gVecSize = std::atoi(argv[i + 1]);
444 i += 2;
445
446 } else if (isCmd(argv[i], "-lv", "--loop-variant") && (i + 1 < argc)) {
447 gGlobal->gVectorLoopVariant = std::atoi(argv[i + 1]);
448 i += 2;
449
450 } else if (isCmd(argv[i], "-omp", "--openmp")) {
451 gGlobal->gOpenMPSwitch = true;
452 i += 1;
453
454 } else if (isCmd(argv[i], "-pl", "--par-loop")) {
455 gGlobal->gOpenMPLoop = true;
456 i += 1;
457
458 } else if (isCmd(argv[i], "-sch", "--scheduler")) {
459 gGlobal->gSchedulerSwitch = true;
460 i += 1;
461
462 } else if (isCmd(argv[i], "-ocl", "--openCL")) {
463 gGlobal->gOpenCLSwitch = true;
464 i += 1;
465
466 } else if (isCmd(argv[i], "-cuda", "--CUDA")) {
467 gGlobal->gCUDASwitch = true;
468 i += 1;
469
470 } else if (isCmd(argv[i], "-g", "--groupTasks")) {
471 gGlobal->gGroupTaskSwitch = true;
472 i += 1;
473
474 } else if (isCmd(argv[i], "-fun", "--funTasks")) {
475 gGlobal->gFunTaskSwitch = true;
476 i += 1;
477
478 } else if (isCmd(argv[i], "-uim", "--user-interface-macros")) {
479 gGlobal->gUIMacroSwitch = true;
480 i += 1;
481
482 } else if (isCmd(argv[i], "-t", "--timeout") && (i + 1 < argc)) {
483 gGlobal->gTimeout = std::atoi(argv[i + 1]);
484 i += 2;
485
486 } else if (isCmd(argv[i], "-time", "--compilation-time")) {
487 gTimingSwitch = true;
488 i += 1;
489
490 // 'real' options
491 } else if (isCmd(argv[i], "-single", "--single-precision-floats")) {
492 if (float_size && gGlobal->gFloatSize != 1) {
493 throw faustexception("ERROR : cannot using -single, -double, -quad or -fx at the same time\n");
494 } else {
495 float_size = true;
496 }
497 gGlobal->gFloatSize = 1;
498 i += 1;
499
500 } else if (isCmd(argv[i], "-double", "--double-precision-floats")) {
501 if (float_size && gGlobal->gFloatSize != 2) {
502 throw faustexception("ERROR : cannot using -single, -double, -quad or -fx at the same time\n");
503 } else {
504 float_size = true;
505 }
506 gGlobal->gFloatSize = 2;
507 i += 1;
508
509 } else if (isCmd(argv[i], "-quad", "--quad-precision-floats")) {
510 if (float_size && gGlobal->gFloatSize != 3) {
511 throw faustexception("ERROR : cannot using -single, -double, -quad or -fx at the same time\n");
512 } else {
513 float_size = true;
514 }
515 gGlobal->gFloatSize = 3;
516 i += 1;
517
518 } else if (isCmd(argv[i], "-fx", "--fixed-point")) {
519 if (float_size && gGlobal->gFloatSize != 4) {
520 throw faustexception("ERROR : cannot using -single, -double, -quad or -fx at the same time\n");
521 } else {
522 float_size = true;
523 }
524 gGlobal->gFloatSize = 4;
525 i += 1;
526
527 } else if (isCmd(argv[i], "-mdoc", "--mathdoc")) {
528 gGlobal->gPrintDocSwitch = true;
529 i += 1;
530
531 } else if (isCmd(argv[i], "-mdlang", "--mathdoc-lang") && (i + 1 < argc)) {
532 gGlobal->gDocLang = argv[i + 1];
533 i += 2;
534
535 } else if (isCmd(argv[i], "-stripmdoc", "--strip-mdoc-tags")) {
536 gGlobal->gStripDocSwitch = true;
537 i += 1;
538
539 } else if (isCmd(argv[i], "-flist", "--file-list")) {
540 gGlobal->gPrintFileListSwitch = true;
541 i += 1;
542
543 } else if (isCmd(argv[i], "-norm", "--normalized-form")) {
544 gGlobal->gDumpNorm = true;
545 i += 1;
546
547 } else if (isCmd(argv[i], "-cn", "--class-name") && (i + 1 < argc)) {
548 vector<char> rep = {'@', ' ', '(', ')', '/', '\\', '.'};
549 gGlobal->gClassName = replaceCharList(argv[i + 1], rep, '_');
550 i += 2;
551
552 } else if (isCmd(argv[i], "-scn", "--super-class-name") && (i + 1 < argc)) {
553 gGlobal->gSuperClassName = argv[i + 1];
554 i += 2;
555
556 } else if (isCmd(argv[i], "-pn", "--process-name") && (i + 1 < argc)) {
557 gGlobal->gProcessName = argv[i + 1];
558 i += 2;
559
560 } else if (isCmd(argv[i], "-i", "--inline-architecture-files")) {
561 gGlobal->gInlineArchSwitch = true;
562 i += 1;
563
564 } else if (isCmd(argv[i], "-e", "--export-dsp")) {
565 gGlobal->gExportDSP = true;
566 i += 1;
567
568 } else if (isCmd(argv[i], "-exp10", "--generate-exp10")) {
569 gGlobal->gHasExp10 = true;
570 i += 1;
571
572 } else if (isCmd(argv[i], "-os", "--one-sample") || isCmd(argv[i], "-os0", "--one-sample0")) {
573 gGlobal->gOneSample = 0;
574 i += 1;
575
576 } else if (isCmd(argv[i], "-os1", "--one-sample1")) {
577 gGlobal->gOneSample = 1;
578 i += 1;
579
580 } else if (isCmd(argv[i], "-cm", "--compute-mix")) {
581 gGlobal->gComputeMix = true;
582 i += 1;
583
584 } else if (isCmd(argv[i], "-ftz", "--flush-to-zero")) {
585 gGlobal->gFTZMode = std::atoi(argv[i + 1]);
586 if ((gGlobal->gFTZMode > 2) || (gGlobal->gFTZMode < 0)) {
587 stringstream error;
588 error << "ERROR : invalid -ftz option: " << gGlobal->gFTZMode << endl;
589 throw faustexception(error.str());
590 }
591 i += 2;
592
593 } else if (isCmd(argv[i], "-rui", "--range-ui")) {
594 gGlobal->gRangeUI = true;
595 i += 1;
596
597 } else if (isCmd(argv[i], "-fm", "--fast-math")) {
598 gGlobal->gFastMath = true;
599 gGlobal->gFastMathLib = argv[i + 1];
600 i += 2;
601
602 } else if (isCmd(argv[i], "-mapp", "--math-approximation")) {
603 gGlobal->gMathApprox = true;
604 i += 1;
605
606 } else if (isCmd(argv[i], "-ns", "--namespace")) {
607 gGlobal->gNameSpace = argv[i + 1];
608 i += 2;
609
610 } else if (isCmd(argv[i], "-I", "--import-dir") && (i + 1 < argc)) {
611 if ((strstr(argv[i + 1], "http://") != 0) || (strstr(argv[i + 1], "https://") != 0)) {
612 // We want to search user given directories *before* the standard ones, so insert at the beginning
613 gGlobal->gImportDirList.insert(gGlobal->gImportDirList.begin(), argv[i + 1]);
614 } else {
615 char temp[PATH_MAX + 1];
616 char* path = realpath(argv[i + 1], temp);
617 if (path) {
618 // We want to search user given directories *before* the standard ones, so insert at the beginning
619 gGlobal->gImportDirList.insert(gGlobal->gImportDirList.begin(), path);
620 }
621 }
622 i += 2;
623
624 } else if (isCmd(argv[i], "-A", "--architecture-dir") && (i + 1 < argc)) {
625 if ((strstr(argv[i + 1], "http://") != 0) || (strstr(argv[i + 1], "https://") != 0)) {
626 gGlobal->gArchitectureDirList.push_back(argv[i + 1]);
627 } else {
628 char temp[PATH_MAX + 1];
629 char* path = realpath(argv[i + 1], temp);
630 if (path) {
631 gGlobal->gArchitectureDirList.push_back(path);
632 }
633 }
634 i += 2;
635
636 } else if (isCmd(argv[i], "-L", "--library") && (i + 1 < argc)) {
637 gGlobal->gLibraryList.push_back(argv[i + 1]);
638 i += 2;
639
640 } else if (isCmd(argv[i], "-O", "--output-dir") && (i + 1 < argc)) {
641 char temp[PATH_MAX + 1];
642 char* path = realpath(argv[i + 1], temp);
643 if (path == 0) {
644 stringstream error;
645 error << "ERROR : invalid directory path " << argv[i + 1] << endl;
646 throw faustexception(error.str());
647 } else {
648 gGlobal->gOutputDir = path;
649 }
650 i += 2;
651
652 } else if (isCmd(argv[i], "-inpl", "--in-place")) {
653 gGlobal->gInPlace = true;
654 i += 1;
655
656 } else if (isCmd(argv[i], "-es", "--enable-semantics")) {
657 gGlobal->gEnableFlag = std::atoi(argv[i + 1]) == 1;
658 i += 2;
659
660 } else if (isCmd(argv[i], "-lcc", "--local-causality-check")) {
661 gGlobal->gLocalCausalityCheck = true;
662 i += 1;
663
664 } else if (isCmd(argv[i], "-light", "--light-mode")) {
665 gGlobal->gLightMode = true;
666 i += 1;
667
668 } else if (isCmd(argv[i], "-clang", "--clang")) {
669 gGlobal->gClang = true;
670 i += 1;
671
672 } else if (isCmd(argv[i], "-ct", "--check-table")) {
673 gGlobal->gCheckTable = "ct";
674 i += 1;
675
676 } else if (isCmd(argv[i], "-cat", "--check-all-table")) {
677 gGlobal->gCheckTable = "cat";
678 i += 1;
679
680 } else if (isCmd(argv[i], "-me", "--math-exceptions")) {
681 gGlobal->gMathExceptions = true;
682 i += 1;
683
684 } else if (isCmd(argv[i], "-lm", "--local-machine") || isCmd(argv[i], "-rm", "--remote-machine") ||
685 isCmd(argv[i], "-poly", "--polyphonic-mode") || isCmd(argv[i], "-voices", "--polyphonic-voices") ||
686 isCmd(argv[i], "-group", "--polyphonic-group")) {
687 // Ignore arg
688 i += 2;
689
690 } else if (argv[i][0] != '-') {
691 const char* url = argv[i];
692 if (checkURL(url)) {
693 gGlobal->gInputFiles.push_back(url);
694 }
695 i++;
696
697 } else {
698 if (err == 0) {
699 parse_error << "unrecognized option(s) : \"" << argv[i] << "\"";
700 } else {
701 parse_error << ",\"" << argv[i] << "\"";
702 }
703 i++;
704 err++;
705 }
706 }
707
708 // Adjust related options
709 if (gGlobal->gOpenMPSwitch || gGlobal->gSchedulerSwitch) gGlobal->gVectorSwitch = true;
710
711 // Check options coherency
712 if (gGlobal->gInPlace && gGlobal->gVectorSwitch) {
713 throw faustexception("ERROR : '-inpl' option can only be used in scalar mode\n");
714 }
715
716 #if 0
717 if (gGlobal->gOutputLang == "ocpp" && gGlobal->gVectorSwitch) {
718 throw faustexception("ERROR : 'ocpp' backend can only be used in scalar mode\n");
719 }
720 #endif
721 if (gGlobal->gOneSample >= 0 && gGlobal->gOutputLang != "cpp" && gGlobal->gOutputLang != "c" && gGlobal->gOutputLang != "dlang" &&
722 !startWith(gGlobal->gOutputLang, "soul") && gGlobal->gOutputLang != "fir") {
723 throw faustexception("ERROR : '-os' option cannot only be used with 'cpp', 'c', 'fir' or 'soul' backends\n");
724 }
725
726 if (gGlobal->gOneSample >= 0 && gGlobal->gVectorSwitch) {
727 throw faustexception("ERROR : '-os' option cannot only be used in scalar mode\n");
728 }
729
730 if (gGlobal->gFTZMode == 2 && gGlobal->gOutputLang == "soul") {
731 throw faustexception("ERROR : '-ftz 2' option cannot be used in 'soul' backend\n");
732 }
733
734 if (gGlobal->gVectorLoopVariant < 0 || gGlobal->gVectorLoopVariant > 1) {
735 stringstream error;
736 error << "ERROR : invalid loop variant [-lv = " << gGlobal->gVectorLoopVariant << "] should be 0 or 1" << endl;
737 throw faustexception(error.str());
738 }
739
740 if (gGlobal->gVecSize < 4) {
741 stringstream error;
742 error << "ERROR : invalid vector size [-vs = " << gGlobal->gVecSize << "] should be at least 4" << endl;
743 throw faustexception(error.str());
744 }
745
746 if (gGlobal->gFunTaskSwitch) {
747 if (!(gGlobal->gOutputLang == "c" || gGlobal->gOutputLang == "cpp" || gGlobal->gOutputLang == "llvm" ||
748 gGlobal->gOutputLang == "fir")) {
749 throw faustexception("ERROR : -fun can only be used with 'c', 'cpp', 'llvm' or 'fir' backends\n");
750 }
751 }
752
753 if (gGlobal->gFastMath) {
754 if (!(gGlobal->gOutputLang == "c" || gGlobal->gOutputLang == "cpp" || gGlobal->gOutputLang == "llvm" ||
755 startWith(gGlobal->gOutputLang, "wast") || startWith(gGlobal->gOutputLang, "wasm"))) {
756 throw faustexception("ERROR : -fm can only be used with 'c', 'cpp', 'llvm' or 'wast/wast' backends\n");
757 }
758 }
759
760 if (gGlobal->gNameSpace != "" && gGlobal->gOutputLang != "cpp" && gGlobal->gOutputLang != "dlang") {
761 throw faustexception("ERROR : -ns can only be used with the 'cpp' or 'dlang' backend\n");
762 }
763
764 if (gGlobal->gMaskDelayLineThreshold < INT_MAX && (gGlobal->gVectorSwitch || (gGlobal->gOutputLang == "ocpp"))) {
765 throw faustexception(
766 "ERROR : '-dlt < INT_MAX' option can only be used in scalar mode and not with the 'ocpp' backend\n");
767 }
768
769 // gComputeMix check
770 if (gGlobal->gComputeMix && gGlobal->gOutputLang == "ocpp") {
771 throw faustexception("ERROR : -cm cannot be used with the 'ocpp' backend\n");
772 }
773
774 if (gGlobal->gComputeMix && gGlobal->gOutputLang == "interp") {
775 throw faustexception("ERROR : -cm cannot be used with the 'interp' backend\n");
776 }
777
778 if (gGlobal->gComputeMix && gGlobal->gOutputLang == "soul") {
779 throw faustexception("ERROR : -cm cannot be used with the 'soul' backend\n");
780 }
781
782 if (gGlobal->gFloatSize == 4 && gGlobal->gOutputLang != "cpp" && gGlobal->gOutputLang != "ocpp" &&
783 gGlobal->gOutputLang != "c") {
784 throw faustexception("ERROR : -fx can ony be used with 'c', 'cpp' or 'ocpp' backends\n");
785 }
786
787 if (gGlobal->gMemoryManager && gGlobal->gOutputLang != "cpp" && gGlobal->gOutputLang != "ocpp") {
788 throw faustexception("ERROR : -mem can ony be used with 'cpp' or 'ocpp' backends\n");
789 }
790
791 if (gGlobal->gArchFile != "" &&
792 ((gGlobal->gOutputLang == "wast") || (gGlobal->gOutputLang == "wasm") || (gGlobal->gOutputLang == "interp") ||
793 (gGlobal->gOutputLang == "llvm") || (gGlobal->gOutputLang == "fir"))) {
794 throw faustexception("ERROR : -a can only be used with 'c', 'cpp', 'ocpp', 'rust' and 'soul' backends\n");
795 }
796
797 if (err != 0) {
798 stringstream error;
799 error << "WARNING : " << parse_error.str() << endl;
800 gGlobal->gErrorMsg = error.str();
801 }
802
803 return (err == 0);
804 }
805
806 /****************************************************************
807 Faust directories information
808 *****************************************************************/
809 #ifdef WIN32
810 #define kPSEP '\\'
811 #else
812 #define kPSEP '/'
813 #endif
814
815 #ifndef LIBDIR
816 #define LIBDIR "lib"
817 #endif
printLibDir()818 static void printLibDir()
819 {
820 cout << gGlobal->gFaustRootDir << kPSEP << LIBDIR << endl;
821 }
printIncludeDir()822 static void printIncludeDir()
823 {
824 cout << gGlobal->gFaustRootDir << kPSEP << "include" << endl;
825 }
printArchDir()826 static void printArchDir()
827 {
828 cout << gGlobal->gFaustRootDir << kPSEP << "share" << kPSEP << "faust" << endl;
829 }
printDspDir()830 static void printDspDir()
831 {
832 cout << gGlobal->gFaustRootDir << kPSEP << "share" << kPSEP << "faust" << endl;
833 }
printPaths()834 static void printPaths()
835 {
836 cout << "FAUST dsp library paths:" << endl;
837 for (auto path : gGlobal->gImportDirList) cout << path << endl;
838 cout << "\nFAUST architectures paths:" << endl;
839 for (auto path : gGlobal->gArchitectureDirList) cout << path << endl;
840 cout << endl;
841 }
842
843 /****************************************************************
844 Help and Version information
845 *****************************************************************/
846
printVersion()847 static void printVersion()
848 {
849 cout << "FAUST Version " << FAUSTVERSION << "\n";
850 cout << "Embedded backends: \n";
851 enumBackends(cout);
852 #ifdef LLVM_BUILD
853 cout << "Build with LLVM version " << LLVM_VERSION << "\n";
854 #endif
855 cout << "Copyright (C) 2002-2021, GRAME - Centre National de Creation Musicale. All rights reserved. \n";
856 }
857
printHelp()858 static void printHelp()
859 {
860 const char* tab = " ";
861 const char* line = "\n---------------------------------------\n";
862
863 cout << "FAUST compiler version " << FAUSTVERSION << "\n";
864 cout << "usage : faust [options] file1 [file2 ...]." << endl;
865 cout << " where options represent zero or more compiler options \n\tand fileN represents a Faust source "
866 "file (.dsp extension)."
867 << endl;
868
869 cout << endl << "Input options:" << line;
870 cout << tab << "-a <file> wrapper architecture file." << endl;
871 cout << tab << "-i --inline-architecture-files inline architecture files." << endl;
872 cout << tab << "-A <dir> --architecture-dir <dir> add the directory <dir> to the architecture search path."
873 << endl;
874 cout << tab << "-I <dir> --import-dir <dir> add the directory <dir> to the import search path." << endl;
875 cout << tab << "-L <file> --library <file> link with the LLVM module <file>." << endl;
876
877 cout << tab << "-t <sec> --timeout <sec> abort compilation after <sec> seconds (default 120)."
878 << endl;
879
880 cout << endl << "Output options:" << line;
881 cout << tab << "-o <file> the output file." << endl;
882 cout << tab << "-e --export-dsp export expanded DSP (with all included libraries)." << endl;
883 cout << tab << "-uim --user-interface-macros add user interface macro definitions to the output code."
884 << endl;
885 cout << tab << "-xml generate an XML description file." << endl;
886 cout << tab << "-json generate a JSON description file." << endl;
887 cout << tab
888 << "-O <dir> --output-dir <dir> specify the relative directory of the generated output code and "
889 "of additional generated files (SVG, XML...)."
890 << endl;
891
892 cout << endl << "Code generation options:" << line;
893 cout << tab << "-lang <lang> --language select output language," << endl;
894 cout << tab
895 << " 'lang' should be c, cpp (default), csharp, dlang, fir, interp, java, julia, llvm, "
896 "ocpp, rust, soul or wast/wasm."
897 << endl;
898 cout << tab
899 << "-single --single-precision-floats use single precision floats for internal computations (default)."
900 << endl;
901 cout << tab << "-double --double-precision-floats use double precision floats for internal computations."
902 << endl;
903 cout << tab << "-quad --quad-precision-floats use quad precision floats for internal computations."
904 << endl;
905 cout << tab << "-fx --fixed-point use fixed-point for internal computations." << endl;
906 cout << tab
907 << "-es 1|0 --enable-semantics 1|0 use enable semantics when 1 (default), and simple multiplication "
908 "otherwise."
909 << endl;
910 cout << tab << "-lcc --local-causality-check check causality also at local level." << endl;
911 cout << tab << "-light --light-mode do not generate the entire DSP API." << endl;
912 cout << tab
913 << "-clang --clang when compiled with clang/clang++, adds specific #pragma for "
914 "auto-vectorization."
915 << endl;
916 cout << tab << "-exp10 --generate-exp10 pow(10,x) replaced by possibly faster exp10(x)." << endl;
917 cout << tab << "-os --one-sample generate one sample computation (same as -os0)." << endl;
918 cout << tab << "-os0 --one-sample0 generate one sample computation (0 = separated control)." << endl;
919 cout << tab << "-os1 --one-sample1 generate one sample computation (1 = separated control and DSP struct)." << endl;
920 cout << tab << "-cm --compute-mix mix in outputs buffers." << endl;
921 cout << tab
922 << "-cn <name> --class-name <name> specify the name of the dsp class to be used instead of mydsp."
923 << endl;
924 cout << tab
925 << "-scn <name> --super-class-name <name> specify the name of the super class to be used instead of dsp."
926 << endl;
927 cout << tab << "-pn <name> --process-name <name> specify the name of the dsp entry-point instead of process."
928 << endl;
929 cout << tab
930 << "-mcd <n> --max-copy-delay <n> threshold between copy and ring buffer implementation (default 16 "
931 "samples)."
932 << endl;
933 cout << tab
934 << "-dlt <n> --delay-line-threshold <n> threshold between 'mask' and 'select' ring buffer implementation "
935 "(default INT_MAX "
936 "samples)."
937 << endl;
938 cout << tab
939 << "-mem --memory allocate static in global state using a custom memory manager."
940 << endl;
941 cout << tab
942 << "-ftz <n> --flush-to-zero <n> code added to recursive signals [0:no (default), 1:fabs based, "
943 "2:mask based (fastest)]."
944 << endl;
945 cout << tab
946 << "-rui --range-ui whether to generate code to limit vslider/hslider/nentry values "
947 "in [min..max] range."
948 << endl;
949 cout
950 << tab
951 << "-inj <f> --inject <f> inject source file <f> into architecture file instead of compiling "
952 "a dsp file."
953 << endl;
954 cout << tab << "-scal --scalar generate non-vectorized code." << endl;
955 cout << tab
956 << "-inpl --in-place generates code working when input and output buffers are the same "
957 "(scalar mode only)."
958 << endl;
959 cout << tab << "-vec --vectorize generate easier to vectorize code." << endl;
960 cout << tab << "-vs <n> --vec-size <n> size of the vector (default 32 samples)." << endl;
961 cout << tab << "-lv <n> --loop-variant <n> [0:fastest (default), 1:simple]." << endl;
962 cout << tab << "-omp --openmp generate OpenMP pragmas, activates --vectorize option."
963 << endl;
964 cout << tab << "-pl --par-loop generate parallel loops in --openmp mode." << endl;
965 cout << tab
966 << "-sch --scheduler generate tasks and use a Work Stealing scheduler, activates "
967 "--vectorize option."
968 << endl;
969 cout << tab << "-ocl --opencl generate tasks with OpenCL (experimental)." << endl;
970 cout << tab << "-cuda --cuda generate tasks with CUDA (experimental)." << endl;
971 cout << tab << "-dfs --deep-first-scheduling schedule vector loops in deep first order." << endl;
972 cout << tab
973 << "-g --group-tasks group single-threaded sequential tasks together when -omp or -sch "
974 "is used."
975 << endl;
976 cout << tab
977 << "-fun --fun-tasks separate tasks code as separated functions (in -vec, -sch, or "
978 "-omp mode)."
979 << endl;
980 cout << tab
981 << "-fm <file> --fast-math <file> use optimized versions of mathematical functions implemented in "
982 "<file>, use 'faust/dsp/fastmath.cpp' when file is 'def'."
983 << endl;
984 cout << tab
985
986 << "-mapp --math-approximation simpler/faster versions of 'floor/ceil/fmod/remainder' functions." << endl;
987 cout << tab
988 << "-ns <name> --namespace <name> generate C++ or D code in a namespace <name>." << endl;
989
990 cout << tab << "-vhdl --vhdl output vhdl file." << endl;
991
992 cout << tab
993 << "-wi <n> --widening-iterations <n> number of iterations before widening in signal bounding."
994 << endl;
995
996 cout << tab
997 << "-ni <n> --narrowing-iterations <n> number of iterations before stopping narrowing in signal bounding."
998 << endl;
999
1000 cout << endl << "Block diagram options:" << line;
1001 cout << tab << "-ps --postscript print block-diagram to a postscript file." << endl;
1002 cout << tab << "-svg --svg print block-diagram to a svg file." << endl;
1003 cout << tab << "-sd --simplify-diagrams try to further simplify diagrams before drawing." << endl;
1004 cout << tab << "-drf --draw-route-frame draw route frames instead of simple cables." << endl;
1005 cout << tab
1006 << "-f <n> --fold <n> threshold to activate folding mode during block-diagram "
1007 "generation (default 25 elements)."
1008 << endl;
1009 cout << tab
1010 << "-fc <n> --fold-complexity <n> complexity threshold to fold an expression in folding mode "
1011 "(default 2)."
1012 << endl;
1013 cout << tab
1014 << "-mns <n> --max-name-size <n> threshold during block-diagram generation (default 40 char)."
1015 << endl;
1016 cout << tab
1017 << "-sn --simple-names use simple names (without arguments) during block-diagram "
1018 "generation."
1019 << endl;
1020 cout << tab << "-blur --shadow-blur add a shadow blur to SVG boxes." << endl;
1021
1022 cout << endl << "Math doc options:" << line;
1023 cout << tab
1024 << "-mdoc --mathdoc print math documentation of the Faust program in LaTeX format in "
1025 "a -mdoc folder."
1026 << endl;
1027 cout << tab << "-mdlang <l> --mathdoc-lang <l> if translation file exists (<l> = en, fr, ...)." << endl;
1028 cout << tab << "-stripmdoc --strip-mdoc-tags strip mdoc tags when printing Faust -mdoc listings."
1029 << endl;
1030
1031 cout << endl << "Debug options:" << line;
1032 cout << tab << "-d --details print compilation details." << endl;
1033 cout << tab << "-time --compilation-time display compilation phases timing information." << endl;
1034 cout << tab << "-flist --file-list print file list (including libraries) used to eval process."
1035 << endl;
1036 cout << tab << "-tg --task-graph print the internal task graph in dot format." << endl;
1037 cout << tab << "-sg --signal-graph print the internal signal graph in dot format." << endl;
1038 cout << tab << "-norm --normalized-form print signals in normalized form and exit." << endl;
1039 cout << tab << "-ct --check-table check table index range and exit at first failure." << endl;
1040 cout << tab << "-cat --check-all-table check all table index range." << endl;
1041 cout << tab << "-me --math-exceptions check / for 0 as denominator and remainder, fmod, sqrt, log10, log, acos, asin functions domain." << endl;
1042
1043 cout << endl << "Information options:" << line;
1044 cout << tab << "-h --help print this help message." << endl;
1045 cout << tab << "-v --version print version information and embedded backends list."
1046 << endl;
1047 cout << tab << "-libdir --libdir print directory containing the Faust libraries." << endl;
1048 cout << tab << "-includedir --includedir print directory containing the Faust headers." << endl;
1049 cout << tab << "-archdir --archdir print directory containing the Faust architectures."
1050 << endl;
1051 cout << tab << "-dspdir --dspdir print directory containing the Faust dsp libraries."
1052 << endl;
1053 cout << tab << "-pathslist --pathslist print the architectures and dsp library paths." << endl;
1054
1055 cout << endl << "Example:" << line;
1056 cout << "faust -a jack-gtk.cpp -o myfx.cpp myfx.dsp" << endl;
1057 }
1058
printDeclareHeader(ostream & dst)1059 static void printDeclareHeader(ostream& dst)
1060 {
1061 for (const auto& i : gGlobal->gMetaDataSet) {
1062 if (i.first != tree("author")) {
1063 dst << "declare ";
1064 stringstream key;
1065 key << *(i.first);
1066 vector<char> to_replace{'.', ':', '/'};
1067 dst << replaceCharList(key.str(), to_replace, '_');
1068 dst << " " << **(i.second.begin()) << ";" << endl;
1069 } else {
1070 for (set<Tree>::iterator j = i.second.begin(); j != i.second.end(); ++j) {
1071 if (j == i.second.begin()) {
1072 dst << "declare " << *(i.first) << " " << **j << ";" << endl;
1073 } else {
1074 dst << "declare contributor " << **j << ";" << endl;
1075 }
1076 }
1077 }
1078 }
1079 }
1080
1081 /****************************************************************
1082 MAIN
1083 *****************************************************************/
1084
1085 #ifdef OCPP_BUILD
1086
printHeader(ostream & dst)1087 static void printHeader(ostream& dst)
1088 {
1089 // defines the metadata we want to print as comments at the begin of in the C++ file
1090 set<Tree> selectedKeys;
1091 selectedKeys.insert(tree("name"));
1092 selectedKeys.insert(tree("author"));
1093 selectedKeys.insert(tree("copyright"));
1094 selectedKeys.insert(tree("license"));
1095 selectedKeys.insert(tree("version"));
1096
1097 dst << "//----------------------------------------------------------" << endl;
1098 for (const auto& i : gGlobal->gMetaDataSet) {
1099 if (selectedKeys.count(i.first)) {
1100 dst << "// " << *(i.first);
1101 const char* sep = ": ";
1102 for (const auto& j : i.second) {
1103 dst << sep << *j;
1104 sep = ", ";
1105 }
1106 dst << endl;
1107 }
1108 }
1109
1110 dst << "//" << endl;
1111 dst << "// Code generated with Faust " << FAUSTVERSION << " (https://faust.grame.fr)" << endl;
1112 dst << "//----------------------------------------------------------" << endl << endl;
1113 }
1114
1115 #endif
1116
1117 /**
1118 * transform a filename "faust/example/noise.dsp" into
1119 * the corresponding fx name "noise"
1120 */
fxName(const string & filename)1121 static string fxName(const string& filename)
1122 {
1123 // determine position right after the last '/' or 0
1124 size_t p1 = 0;
1125 for (size_t i = 0; i < filename.size(); i++) {
1126 if (filename[i] == '/') {
1127 p1 = i + 1;
1128 }
1129 }
1130
1131 // determine position of the last '.'
1132 size_t p2 = filename.size();
1133 for (size_t i = p1; i < filename.size(); i++) {
1134 if (filename[i] == '.') {
1135 p2 = i;
1136 }
1137 }
1138
1139 return filename.substr(p1, p2 - p1);
1140 }
1141
initFaustDirectories(int argc,const char * argv[])1142 static void initFaustDirectories(int argc, const char* argv[])
1143 {
1144 #if !defined(FAUST_SELF_CONTAINED_LIB)
1145 char s[1024];
1146 getFaustPathname(s, 1024);
1147
1148 gGlobal->gFaustExeDir = exepath::get(argv[0]);
1149 gGlobal->gFaustRootDir = exepath::dirup(gGlobal->gFaustExeDir);
1150 gGlobal->gFaustDirectory = fileDirname(s);
1151 gGlobal->gFaustSuperDirectory = fileDirname(gGlobal->gFaustDirectory);
1152 gGlobal->gFaustSuperSuperDirectory = fileDirname(gGlobal->gFaustSuperDirectory);
1153
1154 //-------------------------------------------------------------------------------------
1155 // init gImportDirList : a list of path where to search .lib files
1156 //-------------------------------------------------------------------------------------
1157 if (char* envpath = getenv("FAUST_LIB_PATH")) {
1158 gGlobal->gImportDirList.push_back(envpath);
1159 }
1160 #ifdef INSTALL_PREFIX
1161 gGlobal->gImportDirList.push_back(INSTALL_PREFIX "/share/faust");
1162 #endif
1163
1164 gGlobal->gImportDirList.push_back(exepath::dirup(gGlobal->gFaustExeDir) + "/share/faust");
1165 gGlobal->gImportDirList.push_back("/usr/local/share/faust");
1166 gGlobal->gImportDirList.push_back("/usr/share/faust");
1167
1168 //-------------------------------------------------------------------------------------
1169 // init gArchitectureDirList : a list of path where to search architectures files
1170 //-------------------------------------------------------------------------------------
1171 if (char* envpath = getenv("FAUST_ARCH_PATH")) {
1172 gGlobal->gArchitectureDirList.push_back(envpath);
1173 }
1174 gGlobal->gArchitectureDirList.push_back(gGlobal->gFaustDirectory + "/architecture");
1175 gGlobal->gArchitectureDirList.push_back(gGlobal->gFaustSuperDirectory + "/architecture");
1176 gGlobal->gArchitectureDirList.push_back(gGlobal->gFaustSuperSuperDirectory + "/architecture");
1177 #ifdef INSTALL_PREFIX
1178 gGlobal->gArchitectureDirList.push_back(INSTALL_PREFIX "/share/faust");
1179 gGlobal->gArchitectureDirList.push_back(INSTALL_PREFIX "/include");
1180 #endif
1181 gGlobal->gArchitectureDirList.push_back(exepath::dirup(gGlobal->gFaustExeDir) + "/share/faust");
1182 gGlobal->gArchitectureDirList.push_back(exepath::dirup(gGlobal->gFaustExeDir) + "/include");
1183 gGlobal->gArchitectureDirList.push_back("/usr/local/share/faust");
1184 gGlobal->gArchitectureDirList.push_back("/usr/share/faust");
1185 gGlobal->gArchitectureDirList.push_back("/usr/local/include");
1186 gGlobal->gArchitectureDirList.push_back("/usr/include");
1187
1188 // for debugging purposes
1189 // cerr << "gArchitectureDirList:\n";
1190 // for (auto d : gGlobal->gArchitectureDirList) {
1191 // cerr << "\t" << d << "\n";
1192 // }
1193 // cerr << endl;
1194 #endif
1195 }
1196
initDocumentNames()1197 static void initDocumentNames()
1198 {
1199 if (gGlobal->gInputFiles.empty()) {
1200 gGlobal->gMasterDocument = "Unknown";
1201 gGlobal->gMasterDirectory = ".";
1202 gGlobal->gMasterName = "faustfx";
1203 gGlobal->gDocName = "faustdoc";
1204 } else {
1205 gGlobal->gMasterDocument = *gGlobal->gInputFiles.begin();
1206 gGlobal->gMasterDirectory = fileDirname(gGlobal->gMasterDocument);
1207 gGlobal->gMasterName = fxName(gGlobal->gMasterDocument);
1208 gGlobal->gDocName = fxName(gGlobal->gMasterDocument);
1209 }
1210
1211 // Add gMasterDirectory in gImportDirList and gArchitectureDirList
1212 gGlobal->gImportDirList.push_back(gGlobal->gMasterDirectory);
1213 gGlobal->gArchitectureDirList.push_back(gGlobal->gMasterDirectory);
1214 }
1215
parseSourceFiles()1216 static void parseSourceFiles()
1217 {
1218 startTiming("parser");
1219
1220 list<string>::iterator s;
1221 gGlobal->gResult2 = gGlobal->nil;
1222
1223 if (!gGlobal->gInjectFlag && gGlobal->gInputFiles.begin() == gGlobal->gInputFiles.end()) {
1224 throw faustexception("ERROR : no files specified; for help type \"faust --help\"\n");
1225 }
1226 for (s = gGlobal->gInputFiles.begin(); s != gGlobal->gInputFiles.end(); s++) {
1227 if (s == gGlobal->gInputFiles.begin()) {
1228 gGlobal->gMasterDocument = *s;
1229 }
1230 gGlobal->gResult2 = cons(importFile(tree(s->c_str())), gGlobal->gResult2);
1231 }
1232
1233 gGlobal->gExpandedDefList = gGlobal->gReader.expandList(gGlobal->gResult2);
1234
1235 endTiming("parser");
1236 }
1237
evaluateBlockDiagram(Tree expandedDefList,int & numInputs,int & numOutputs)1238 static Tree evaluateBlockDiagram(Tree expandedDefList, int& numInputs, int& numOutputs)
1239 {
1240 startTiming("evaluation");
1241
1242 Tree process = evalprocess(expandedDefList);
1243 if (gGlobal->gErrorCount > 0) {
1244 stringstream error;
1245 error << "ERROR : total of " << gGlobal->gErrorCount << " errors during the compilation of "
1246 << gGlobal->gMasterDocument << endl;
1247 throw faustexception(error.str());
1248 }
1249
1250 if (gGlobal->gDetailsSwitch) {
1251 cout << "process = " << boxpp(process) << ";\n";
1252 }
1253
1254 if (!getBoxType(process, &numInputs, &numOutputs)) {
1255 stringstream error;
1256 error << "ERROR during the evaluation of process : " << boxpp(process) << endl;
1257 throw faustexception(error.str());
1258 }
1259
1260 if (gGlobal->gDrawPSSwitch) {
1261 drawSchema(process, subst("$0-ps", gGlobal->makeDrawPathNoExt()).c_str(), "ps");
1262 }
1263
1264 if (gGlobal->gDrawSVGSwitch) {
1265 drawSchema(process, subst("$0-svg", gGlobal->makeDrawPathNoExt()).c_str(), "svg");
1266 }
1267
1268 if (gGlobal->gDetailsSwitch) {
1269 cout << "process has " << numInputs << " inputs, and " << numOutputs << " outputs" << endl;
1270 }
1271
1272 endTiming("evaluation");
1273
1274 if (gGlobal->gPrintFileListSwitch) {
1275 cout << "---------------------------\n";
1276 cout << "List of file dependencies :\n";
1277 cout << "---------------------------\n";
1278 // print the pathnames of the files used to evaluate process
1279 vector<string> pathnames = gGlobal->gReader.listSrcFiles();
1280 for (size_t i = 0; i < pathnames.size(); i++) cout << pathnames[i] << endl;
1281 cout << "---------------------------\n";
1282 cout << endl;
1283 }
1284
1285 return process;
1286 }
1287
includeFile(const string & file,ostream & dst)1288 static void includeFile(const string& file, ostream& dst)
1289 {
1290 unique_ptr<ifstream> file_include = openArchStream(file.c_str());
1291 if (file_include != nullptr) {
1292 streamCopyUntilEnd(*file_include.get(), dst);
1293 }
1294 }
1295
injectCode(unique_ptr<ifstream> & enrobage1,ostream & dst)1296 static void injectCode(unique_ptr<ifstream>& enrobage1, ostream& dst)
1297 {
1298 /****************************************************************
1299 1.7 - Inject code instead of compile
1300 *****************************************************************/
1301
1302 // Check if this is a code injection
1303 if (gGlobal->gInjectFlag) {
1304 if (gGlobal->gArchFile == "") {
1305 stringstream error;
1306 error << "ERROR : no architecture file specified to inject \"" << gGlobal->gInjectFile << "\"" << endl;
1307 throw faustexception(error.str());
1308 } else {
1309 streamCopyUntil(*enrobage1.get(), dst, "<<includeIntrinsic>>");
1310 container->printMacros(dst, 0);
1311 streamCopyUntil(*enrobage1.get(), dst, "<<includeclass>>");
1312 streamCopyUntilEnd(*injcode.get(), dst);
1313 streamCopyUntilEnd(*enrobage1.get(), dst);
1314 }
1315 throw faustexception("");
1316 }
1317 }
1318
compileCLLVM(Tree signals,int numInputs,int numOutputs,bool generate)1319 static void compileCLLVM(Tree signals, int numInputs, int numOutputs, bool generate)
1320 {
1321 #ifdef CLANG_BUILD
1322 // FIR is generated with internal real instead of FAUSTFLOAT (see InstBuilder::genBasicTyped)
1323 gGlobal->gFAUSTFLOAT2Internal = true;
1324
1325 container = ClangCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs);
1326
1327 if (generate) {
1328 // TO CHECK ?
1329 } else {
1330 // To trigger 'sig.dot' generation
1331 if (gGlobal->gVectorSwitch) {
1332 new_comp = new DAGInstructionsCompiler(container);
1333 } else {
1334 new_comp = new InstructionsCompiler(container);
1335 }
1336 new_comp->prepare(signals);
1337 }
1338 #else
1339 throw faustexception("ERROR : -lang cllcm not supported since LLVM backend is not built\n");
1340 #endif
1341 }
1342
compileLLVM(Tree signals,int numInputs,int numOutputs,bool generate)1343 static void compileLLVM(Tree signals, int numInputs, int numOutputs, bool generate)
1344 {
1345 #ifdef LLVM_BUILD
1346 container = LLVMCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs);
1347
1348 // libc functions will be found by the LLVM linker, but not user defined ones...
1349 gGlobal->gAllowForeignFunction = false;
1350 // FIR is generated with internal real instead of FAUSTFLOAT (see InstBuilder::genBasicTyped)
1351 gGlobal->gFAUSTFLOAT2Internal = true;
1352
1353 gGlobal->gUseDefaultSound = false;
1354
1355 if (gGlobal->gVectorSwitch) {
1356 new_comp = new DAGInstructionsCompiler(container);
1357 } else {
1358 new_comp = new InstructionsCompiler(container);
1359 }
1360
1361 if (gGlobal->gPrintXMLSwitch || gGlobal->gPrintDocSwitch) new_comp->setDescription(new Description());
1362
1363 if (generate) {
1364 new_comp->compileMultiSignal(signals);
1365 } else {
1366 // To trigger 'sig.dot' generation
1367 new_comp->prepare(signals);
1368 }
1369 #else
1370 throw faustexception("ERROR : -lang llvm not supported since LLVM backend is not built\n");
1371 #endif
1372 }
1373
compileInterp(Tree signals,int numInputs,int numOutputs,bool generate)1374 static void compileInterp(Tree signals, int numInputs, int numOutputs, bool generate)
1375 {
1376 #ifdef INTERP_BUILD
1377 if (gGlobal->gFloatSize == 1) {
1378 container = InterpreterCodeContainer<float>::createContainer(gGlobal->gClassName, numInputs, numOutputs);
1379 } else if (gGlobal->gFloatSize == 2) {
1380 container = InterpreterCodeContainer<double>::createContainer(gGlobal->gClassName, numInputs, numOutputs);
1381 } else {
1382 throw faustexception("ERROR : quad format not supported in Interp\n");
1383 }
1384 gGlobal->gAllowForeignFunction = false; // No foreign functions
1385 gGlobal->gAllowForeignConstant = false; // No foreign constant
1386 gGlobal->gAllowForeignVar = false; // No foreign variable
1387 // gGlobal->gComputeIOTA = true; // Ensure IOTA base fixed delays are computed once
1388
1389 // FIR is generated with internal real instead of FAUSTFLOAT (see InstBuilder::genBasicTyped)
1390 gGlobal->gFAUSTFLOAT2Internal = true;
1391 gGlobal->gNeedManualPow = false; // Standard pow function will be used in pow(x,y) when Y in an integer
1392 gGlobal->gRemoveVarAddress = true; // To be used in -vec mode
1393
1394 if (gGlobal->gVectorSwitch) {
1395 new_comp = new DAGInstructionsCompiler(container);
1396 } else {
1397 new_comp = new InterpreterInstructionsCompiler(container);
1398 }
1399
1400 if (gGlobal->gPrintXMLSwitch || gGlobal->gPrintDocSwitch) new_comp->setDescription(new Description());
1401
1402 new_comp->compileMultiSignal(signals);
1403 #else
1404 throw faustexception("ERROR : -lang interp not supported since Interpreter backend is not built\n");
1405 #endif
1406 }
1407
compileFIR(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out)1408 static void compileFIR(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out)
1409 {
1410 #ifdef FIR_BUILD
1411 container = FIRCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs, out, true);
1412
1413 if (gGlobal->gVectorSwitch) {
1414 new_comp = new DAGInstructionsCompiler(container);
1415 } else {
1416 new_comp = new InstructionsCompiler(container);
1417 }
1418
1419 new_comp->compileMultiSignal(signals);
1420 #else
1421 throw faustexception("ERROR : -lang fir not supported since FIR backend is not built\n");
1422 #endif
1423 }
1424
compileC(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out)1425 static void compileC(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out)
1426 {
1427 #ifdef C_BUILD
1428 container = CCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs, out);
1429 #else
1430 throw faustexception("ERROR : -lang c not supported since C backend is not built\n");
1431 #endif
1432 }
1433
compileCPP(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out)1434 static void compileCPP(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out)
1435 {
1436 #ifdef CPP_BUILD
1437 container = CPPCodeContainer::createContainer(gGlobal->gClassName, gGlobal->gSuperClassName, numInputs, numOutputs, out);
1438 #else
1439 throw faustexception("ERROR : -lang cpp not supported since CPP backend is not built\n");
1440 #endif
1441 }
1442
compileOCPP(Tree signals,int numInputs,int numOutputs,bool generate)1443 static void compileOCPP(Tree signals, int numInputs, int numOutputs, bool generate)
1444 {
1445 #ifdef OCPP_BUILD
1446 if (gGlobal->gSchedulerSwitch) {
1447 old_comp = new SchedulerCompiler(gGlobal->gClassName, gGlobal->gSuperClassName, numInputs, numOutputs);
1448 } else if (gGlobal->gVectorSwitch) {
1449 old_comp = new VectorCompiler(gGlobal->gClassName, gGlobal->gSuperClassName, numInputs, numOutputs);
1450 } else {
1451 old_comp = new ScalarCompiler(gGlobal->gClassName, gGlobal->gSuperClassName, numInputs, numOutputs);
1452 }
1453
1454 if (gGlobal->gPrintXMLSwitch || gGlobal->gPrintDocSwitch) old_comp->setDescription(new Description());
1455
1456 old_comp->compileMultiSignal(signals);
1457 #else
1458 throw faustexception("ERROR : -lang ocpp not supported since old CPP backend is not built\n");
1459 #endif
1460 }
1461
compileRust(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out)1462 static void compileRust(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out)
1463 {
1464 #ifdef RUST_BUILD
1465 // FIR is generated with internal real instead of FAUSTFLOAT (see InstBuilder::genBasicTyped)
1466 gGlobal->gFAUSTFLOAT2Internal = true;
1467 container = RustCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs, out);
1468 #else
1469 throw faustexception("ERROR : -lang rust not supported since Rust backend is not built\n");
1470 #endif
1471 }
1472
compileJava(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out)1473 static void compileJava(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out)
1474 {
1475 #ifdef JAVA_BUILD
1476 gGlobal->gAllowForeignFunction = false; // No foreign functions
1477 container = JAVACodeContainer::createContainer(gGlobal->gClassName, gGlobal->gSuperClassName, numInputs, numOutputs, out);
1478 #else
1479 throw faustexception("ERROR : -lang java not supported since JAVA backend is not built\n");
1480 #endif
1481 }
1482
compileJulia(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out)1483 static void compileJulia(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out)
1484 {
1485 #ifdef JULIA_BUILD
1486 gGlobal->gAllowForeignFunction = false; // No foreign functions
1487 container = JuliaCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs, out);
1488 #else
1489 throw faustexception("ERROR : -lang julia not supported since Julia backend is not built\n");
1490 #endif
1491 }
1492
compileCSharp(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out)1493 static void compileCSharp(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out)
1494 {
1495 #ifdef CSHARP_BUILD
1496 gGlobal->gAllowForeignFunction = false; // No foreign functions
1497 container = CSharpCodeContainer::createContainer(gGlobal->gClassName, gGlobal->gSuperClassName, numInputs, numOutputs, out);
1498 #else
1499 throw faustexception("ERROR : -lang csharp not supported since CSharp backend is not built\n");
1500 #endif
1501 }
1502
compileSOUL(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out)1503 static void compileSOUL(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out)
1504 {
1505 #ifdef SOUL_BUILD
1506 gGlobal->gAllowForeignFunction = false; // No foreign functions
1507 gGlobal->gAllowForeignConstant = false; // No foreign constant
1508 gGlobal->gAllowForeignVar = false; // No foreign variable
1509
1510 // FIR is generated with internal real instead of FAUSTFLOAT (see InstBuilder::genBasicTyped)
1511 gGlobal->gFAUSTFLOAT2Internal = true;
1512
1513 // "one sample control" model by default;
1514 gGlobal->gOneSampleControl = true;
1515 gGlobal->gNeedManualPow = false; // Standard pow function will be used in pow(x,y) when Y in an integer
1516
1517 container = SOULCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs, out);
1518 #else
1519 throw faustexception("ERROR : -lang rust not supported since SOUL backend is not built\n");
1520 #endif
1521 }
1522
createHelperFile(const string & outpath)1523 static void createHelperFile(const string& outpath)
1524 {
1525 // Additional file with JS code
1526 if (gGlobal->gOutputFile == "binary") {
1527 // Nothing
1528 } else if (gGlobal->gOutputFile != "") {
1529 string outpath_js;
1530 bool res = replaceExtension(outpath, ".js", outpath_js);
1531 if (res) {
1532 helpers = unique_ptr<ostream>(new ofstream(outpath_js.c_str()));
1533 } else {
1534 cerr << "WARNING : cannot generate helper JS file, outpath is incorrect : \"" << outpath << "\"" << endl;
1535 }
1536 } else {
1537 helpers = unique_ptr<ostream>(new ostringstream());
1538 }
1539 }
1540
compileWAST(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out,const string & outpath)1541 static void compileWAST(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out, const string& outpath)
1542 {
1543 #ifdef WASM_BUILD
1544 gGlobal->gAllowForeignFunction = false; // No foreign functions
1545 gGlobal->gAllowForeignConstant = false; // No foreign constant
1546 gGlobal->gAllowForeignVar = false; // No foreign variable
1547
1548 // FIR is generated with internal real instead of FAUSTFLOAT (see InstBuilder::genBasicTyped)
1549 gGlobal->gFAUSTFLOAT2Internal = true;
1550 // the 'i' variable used in the scalar loop moves by bytes instead of frames
1551 gGlobal->gLoopVarInBytes = true;
1552 gGlobal->gWaveformInDSP = true; // waveform are allocated in the DSP and not as global data
1553 gGlobal->gMachinePtrSize = 4; // WASM is currently 32 bits
1554 gGlobal->gNeedManualPow = false; // Standard pow function will be used in pow(x,y) when Y in an integer
1555 gGlobal->gRemoveVarAddress = true; // To be used in -vec mode
1556 // gGlobal->gHasTeeLocal = true; // combined store/load
1557
1558 gGlobal->gUseDefaultSound = false;
1559
1560 // This speedup (freeverb for instance) ==> to be done at signal level
1561 // gGlobal->gComputeIOTA = true; // Ensure IOTA base fixed delays are computed once
1562
1563 container = WASTCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs, out,
1564 ((gGlobal->gOutputLang == "wast") || (gGlobal->gOutputLang == "wast-i")));
1565 createHelperFile(outpath);
1566 #else
1567 throw faustexception("ERROR : -lang wast not supported since WAST backend is not built\n");
1568 #endif
1569 }
1570
compileWASM(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out,const string & outpath)1571 static void compileWASM(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out, const string& outpath)
1572 {
1573 #ifdef WASM_BUILD
1574 gGlobal->gAllowForeignFunction = false; // No foreign functions
1575 gGlobal->gAllowForeignConstant = false; // No foreign constant
1576 gGlobal->gAllowForeignVar = false; // No foreign variable
1577
1578 // FIR is generated with internal real instead of FAUSTFLOAT (see InstBuilder::genBasicTyped)
1579 gGlobal->gFAUSTFLOAT2Internal = true;
1580 // the 'i' variable used in the scalar loop moves by bytes instead of frames
1581 gGlobal->gLoopVarInBytes = true;
1582 gGlobal->gWaveformInDSP = true; // waveform are allocated in the DSP and not as global data
1583 gGlobal->gMachinePtrSize = 4; // WASM is currently 32 bits
1584 gGlobal->gNeedManualPow = false; // Standard pow function will be used in pow(x,y) when Y in an integer
1585 gGlobal->gRemoveVarAddress = true; // To be used in -vec mode
1586 // gGlobal->gHasTeeLocal = true; // combined store/load
1587
1588 gGlobal->gUseDefaultSound = false;
1589
1590 // This speedup (freeverb for instance) ==> to be done at signal level
1591 // gGlobal->gComputeIOTA = true; // Ensure IOTA base fixed delays are computed once
1592
1593 container = WASMCodeContainer::createContainer(gGlobal->gClassName, numInputs, numOutputs, out,
1594 ((gGlobal->gOutputLang == "wasm")
1595 || (gGlobal->gOutputLang == "wasm-i")
1596 || (gGlobal->gOutputLang == "wasm-ib")));
1597 createHelperFile(outpath);
1598 #else
1599 throw faustexception("ERROR : -lang wasm not supported since WASM backend is not built\n");
1600 #endif
1601 }
1602
compileDlang(Tree signals,int numInputs,int numOutputs,bool generate,ostream * out)1603 static void compileDlang(Tree signals, int numInputs, int numOutputs, bool generate, ostream* out)
1604 {
1605 #ifdef DLANG_BUILD
1606 container = DLangCodeContainer::createContainer(gGlobal->gClassName, gGlobal->gSuperClassName, numInputs, numOutputs, out);
1607 #else
1608 throw faustexception("ERROR : -lang dlang not supported since D backend is not built\n");
1609 #endif
1610 }
1611
generateCode(Tree signals,int numInputs,int numOutputs,bool generate)1612 void generateCode(Tree signals, int numInputs, int numOutputs, bool generate)
1613 {
1614 unique_ptr<ostream> dst;
1615 string outpath;
1616
1617 // MANDATORY: use ostringstream which is indeed a subclass of ostream (otherwise subtle dynamic_cast related crash
1618 // can occur...)
1619
1620 // Finally output file
1621 if (gGlobal->gOutputFile == "string") {
1622 dst = unique_ptr<ostream>(new ostringstream());
1623 } else if (gGlobal->gOutputFile == "binary") {
1624 dst = unique_ptr<ostream>(new ostringstream(ostringstream::out | ostringstream::binary));
1625 } else if (gGlobal->gOutputFile != "") {
1626 outpath = (gGlobal->gOutputDir != "")
1627 ? (gGlobal->gOutputDir + "/" + gGlobal->gOutputFile) : gGlobal->gOutputFile;
1628
1629 unique_ptr<ofstream> fdst = unique_ptr<ofstream>(new ofstream(outpath.c_str()));
1630 if (!fdst->is_open()) {
1631 stringstream error;
1632 error << "ERROR : file '" << outpath << "' cannot be opened\n";
1633 throw faustexception(error.str());
1634 } else {
1635 dst = move(fdst);
1636 }
1637
1638 } else {
1639 dst = unique_ptr<ostream>(new ostringstream());
1640 }
1641
1642 startTiming("generateCode");
1643
1644 if (gGlobal->gOutputLang == "cllvm") {
1645 compileCLLVM(signals, numInputs, numOutputs, generate);
1646 } else if (gGlobal->gOutputLang == "llvm") {
1647 compileLLVM(signals, numInputs, numOutputs, generate);
1648 } else if (gGlobal->gOutputLang == "interp") {
1649 compileInterp(signals, numInputs, numOutputs, generate);
1650 } else if (gGlobal->gOutputLang == "fir") {
1651 compileFIR(signals, numInputs, numOutputs, generate, dst.get());
1652 } else {
1653 if (gGlobal->gOutputLang == "c") {
1654 compileC(signals, numInputs, numOutputs, generate, dst.get());
1655 } else if (gGlobal->gOutputLang == "cpp") {
1656 compileCPP(signals, numInputs, numOutputs, generate, dst.get());
1657 } else if (gGlobal->gOutputLang == "ocpp") {
1658 compileOCPP(signals, numInputs, numOutputs, generate);
1659 } else if (gGlobal->gOutputLang == "rust") {
1660 compileRust(signals, numInputs, numOutputs, generate, dst.get());
1661 } else if (gGlobal->gOutputLang == "java") {
1662 compileJava(signals, numInputs, numOutputs, generate, dst.get());
1663 } else if (gGlobal->gOutputLang == "julia") {
1664 compileJulia(signals, numInputs, numOutputs, generate, dst.get());
1665 } else if (gGlobal->gOutputLang == "csharp") {
1666 compileCSharp(signals, numInputs, numOutputs, generate, dst.get());
1667 } else if (startWith(gGlobal->gOutputLang, "soul")) {
1668 compileSOUL(signals, numInputs, numOutputs, generate, dst.get());
1669 } else if (startWith(gGlobal->gOutputLang, "wast")) {
1670 compileWAST(signals, numInputs, numOutputs, generate, dst.get(), outpath);
1671 } else if (startWith(gGlobal->gOutputLang, "wasm")) {
1672 compileWASM(signals, numInputs, numOutputs, generate, dst.get(), outpath);
1673 } else if (startWith(gGlobal->gOutputLang, "dlang")) {
1674 compileDlang(signals, numInputs, numOutputs, generate, dst.get());
1675 } else {
1676 stringstream error;
1677 error << "ERROR : cannot find backend for "
1678 << "\"" << gGlobal->gOutputLang << "\"" << endl;
1679 throw faustexception(error.str());
1680 }
1681
1682 // New compiler
1683 if (container) {
1684
1685 if (gGlobal->gVectorSwitch) {
1686 new_comp = new DAGInstructionsCompiler(container);
1687 }
1688 #if defined(RUST_BUILD) || defined(JULIA_BUILD)
1689 else if (gGlobal->gOutputLang == "rust" || gGlobal->gOutputLang == "julia") {
1690 new_comp = new InstructionsCompiler1(container);
1691 }
1692 #endif
1693 else {
1694 new_comp = new InstructionsCompiler(container);
1695 }
1696
1697 if (gGlobal->gPrintXMLSwitch || gGlobal->gPrintDocSwitch) new_comp->setDescription(new Description());
1698 new_comp->compileMultiSignal(signals);
1699 }
1700 }
1701
1702 /****************************************************************
1703 * generate output file
1704 ****************************************************************/
1705
1706 if (new_comp) {
1707 if (gGlobal->gArchFile != "") {
1708 // Keep current directory
1709 char buffer[FAUST_PATH_MAX];
1710 char* current_directory = getcwd(buffer, FAUST_PATH_MAX);
1711
1712 if ((enrobage = openArchStream(gGlobal->gArchFile.c_str())) != nullptr) {
1713 if (gGlobal->gNameSpace != "" && gGlobal->gOutputLang == "cpp")
1714 *dst.get() << "namespace " << gGlobal->gNameSpace << " {" << endl;
1715 #ifdef DLANG_BUILD
1716 else if (gGlobal->gOutputLang == "dlang") {
1717 DLangCodeContainer::printDRecipeComment(*dst.get(), container->getClassName());
1718 DLangCodeContainer::printDModuleStmt(*dst.get(), container->getClassName());
1719 }
1720 #endif
1721
1722 // Possibly inject code
1723 injectCode(enrobage, *dst.get());
1724
1725 container->printHeader();
1726
1727 streamCopyUntil(*enrobage.get(), *dst.get(), "<<includeIntrinsic>>");
1728 streamCopyUntil(*enrobage.get(), *dst.get(), "<<includeclass>>");
1729
1730 if (gGlobal->gOpenCLSwitch || gGlobal->gCUDASwitch) {
1731 includeFile("thread.h", *dst.get());
1732 }
1733
1734 container->printFloatDef();
1735 container->produceClass();
1736
1737 streamCopyUntilEnd(*enrobage.get(), *dst.get());
1738
1739 if (gGlobal->gSchedulerSwitch) {
1740 includeFile("scheduler.cpp", *dst.get());
1741 }
1742
1743 container->printFooter();
1744
1745 // Generate factory
1746 gGlobal->gDSPFactory = container->produceFactory();
1747
1748 if (gGlobal->gOutputFile == "string") {
1749 gGlobal->gDSPFactory->write(dst.get(), false, false);
1750 } else if (gGlobal->gOutputFile == "binary") {
1751 gGlobal->gDSPFactory->write(dst.get(), true, false);
1752 } else if (gGlobal->gOutputFile != "") {
1753 // Binary mode for LLVM backend if output different of 'cout'
1754 gGlobal->gDSPFactory->write(dst.get(), true, false);
1755 } else {
1756 gGlobal->gDSPFactory->write(&cout, false, false);
1757 }
1758
1759 // Restore current_directory
1760 if (current_directory) {
1761 if (chdir(current_directory)) { // return code is 0 on successful completion
1762 cerr << "can't restore current directory (" << current_directory << ")" << endl;
1763 }
1764 }
1765
1766 if (gGlobal->gNameSpace != "" && gGlobal->gOutputLang == "cpp")
1767 *dst.get() << "} // namespace " << gGlobal->gNameSpace << endl;
1768
1769 } else {
1770 stringstream error;
1771 error << "ERROR : can't open architecture file " << gGlobal->gArchFile << endl;
1772 throw faustexception(error.str());
1773 }
1774
1775 } else {
1776 container->printHeader();
1777 container->printFloatDef();
1778 container->produceClass();
1779 container->printFooter();
1780
1781 // Generate factory
1782 gGlobal->gDSPFactory = container->produceFactory();
1783
1784 if (gGlobal->gOutputFile == "string") {
1785 gGlobal->gDSPFactory->write(dst.get(), false, false);
1786 if (helpers != nullptr) gGlobal->gDSPFactory->writeHelper(helpers.get(), false, false);
1787 } else if (gGlobal->gOutputFile == "binary") {
1788 gGlobal->gDSPFactory->write(dst.get(), true, false);
1789 if (helpers != nullptr) gGlobal->gDSPFactory->writeHelper(helpers.get(), true, false);
1790 } else if (gGlobal->gOutputFile != "") {
1791 // Binary mode for LLVM backend if output different of 'cout'
1792 gGlobal->gDSPFactory->write(dst.get(), true, false);
1793 if (helpers != nullptr) gGlobal->gDSPFactory->writeHelper(helpers.get(), false, false);
1794 } else {
1795 gGlobal->gDSPFactory->write(&cout, false, false);
1796 if (helpers != nullptr) gGlobal->gDSPFactory->writeHelper(&cout, false, false);
1797 }
1798 }
1799
1800 endTiming("generateCode");
1801
1802 #ifdef OCPP_BUILD
1803 } else if (old_comp) {
1804 // Check for architecture file
1805 if (gGlobal->gArchFile != "") {
1806 if ((enrobage = openArchStream(gGlobal->gArchFile.c_str())) == nullptr) {
1807 stringstream error;
1808 error << "ERROR : can't open architecture file " << gGlobal->gArchFile << endl;
1809 throw faustexception(error.str());
1810 }
1811 }
1812
1813 // Possibly inject code
1814 injectCode(enrobage, *dst.get());
1815
1816 printHeader(*dst);
1817 old_comp->getClass()->printLibrary(*dst.get());
1818 old_comp->getClass()->printIncludeFile(*dst.get());
1819 old_comp->getClass()->printAdditionalCode(*dst.get());
1820
1821 if (gGlobal->gArchFile != "") {
1822 streamCopyUntil(*enrobage.get(), *dst.get(), "<<includeIntrinsic>>");
1823
1824 if (gGlobal->gSchedulerSwitch) {
1825 unique_ptr<ifstream> scheduler_include = openArchStream("old-scheduler.cpp");
1826 if (scheduler_include) {
1827 streamCopyUntilEnd(*scheduler_include, *dst.get());
1828 } else {
1829 throw("ERROR : can't include \"old-scheduler.cpp\", file not found>\n");
1830 }
1831 }
1832
1833 streamCopyUntil(*enrobage.get(), *dst.get(), "<<includeclass>>");
1834 printfloatdef(*dst.get());
1835 old_comp->getClass()->println(0, *dst.get());
1836 streamCopyUntilEnd(*enrobage.get(), *dst.get());
1837
1838 } else {
1839 printfloatdef(*dst.get());
1840 old_comp->getClass()->println(0, *dst.get());
1841 }
1842
1843 /****************************************************************
1844 9 - generate the task graph file in dot format
1845 *****************************************************************/
1846
1847 if (gGlobal->gGraphSwitch) {
1848 ofstream dotfile(subst("$0.dot", gGlobal->makeDrawPath()).c_str());
1849 old_comp->getClass()->printGraphDotFormat(dotfile);
1850 }
1851
1852 if (gGlobal->gOutputFile == "") {
1853 cout << dynamic_cast<ostringstream*>(dst.get())->str();
1854 }
1855
1856 #endif
1857 } else {
1858 faustassert(false);
1859 }
1860 }
1861
printXML(Description * D,int inputs,int outputs)1862 static void printXML(Description* D, int inputs, int outputs)
1863 {
1864 faustassert(D);
1865 ofstream xout(subst("$0.xml", gGlobal->makeDrawPath()).c_str());
1866
1867 MetaDataSet::const_iterator it1;
1868 set<Tree>::const_iterator it2;
1869 for (const auto& it1 : gGlobal->gMetaDataSet) {
1870 const string key = tree2str(it1.first);
1871 for (it2 = it1.second.begin(); it2 != it1.second.end(); ++it2) {
1872 const string value = tree2str(*it2);
1873 if (key == "name") {
1874 D->name(value);
1875 } else if (key == "author") {
1876 D->author(value);
1877 } else if (key == "copyright") {
1878 D->copyright(value);
1879 } else if (key == "license") {
1880 D->license(value);
1881 } else if (key == "version") {
1882 D->version(value);
1883 } else {
1884 D->declare(key, value);
1885 }
1886 }
1887 }
1888
1889 D->className(gGlobal->gClassName);
1890 D->inputs(inputs);
1891 D->outputs(outputs);
1892 D->print(0, xout);
1893 }
1894
generateOutputFiles()1895 static void generateOutputFiles()
1896 {
1897 /****************************************************************
1898 1 - generate XML description (if required)
1899 *****************************************************************/
1900
1901 if (gGlobal->gPrintXMLSwitch) {
1902 if (new_comp) {
1903 printXML(new_comp->getDescription(), container->inputs(), container->outputs());
1904 #ifdef OCPP_BUILD
1905 } else if (old_comp) {
1906 printXML(old_comp->getDescription(), old_comp->getClass()->inputs(), old_comp->getClass()->outputs());
1907 #endif
1908 } else {
1909 faustassert(false);
1910 }
1911 }
1912
1913 /****************************************************************
1914 2 - generate documentation from Faust comments (if required)
1915 *****************************************************************/
1916
1917 if (gGlobal->gPrintDocSwitch && gGlobal->gLatexDocSwitch) {
1918 printDoc(subst("$0-mdoc", gGlobal->makeDrawPathNoExt()).c_str(), "tex", FAUSTVERSION);
1919 }
1920
1921 /****************************************************************
1922 3 - generate the task graph file in dot format
1923 *****************************************************************/
1924
1925 if (gGlobal->gGraphSwitch) {
1926 ofstream dotfile(subst("$0.dot", gGlobal->makeDrawPath()).c_str());
1927 if (new_comp) {
1928 container->printGraphDotFormat(dotfile);
1929 #ifdef OCPP_BUILD
1930 } else if (old_comp) {
1931 old_comp->getClass()->printGraphDotFormat(dotfile);
1932 #endif
1933 } else {
1934 faustassert(false);
1935 }
1936 }
1937 }
1938
expandDSPInternal(int argc,const char * argv[],const char * name,const char * dsp_content)1939 static string expandDSPInternal(int argc, const char* argv[], const char* name, const char* dsp_content)
1940 {
1941 /****************************************************************
1942 1 - process command line
1943 *****************************************************************/
1944 initFaustDirectories(argc, argv);
1945 processCmdline(argc, argv);
1946
1947 /****************************************************************
1948 2 - parse source files
1949 *****************************************************************/
1950 if (dsp_content) {
1951 gGlobal->gInputString = dsp_content;
1952 gGlobal->gInputFiles.push_back(name);
1953 }
1954 initDocumentNames();
1955 initFaustFloat();
1956
1957 parseSourceFiles();
1958
1959 /****************************************************************
1960 3 - evaluate 'process' definition
1961 *****************************************************************/
1962 callFun(threadEvaluateBlockDiagram); // In a thread with more stack size...
1963 if (!gGlobal->gProcessTree) {
1964 throw faustexception(gGlobal->gErrorMessage);
1965 }
1966
1967 // Encode compilation options as a 'declare' : has to be located first in the string
1968 stringstream out;
1969 out << COMPILATION_OPTIONS << reorganizeCompilationOptions(argc, argv) << ';' << endl;
1970
1971 // Encode all libraries paths as 'declare'
1972 vector<string> pathnames = gGlobal->gReader.listSrcFiles();
1973 // Remove DSP filename
1974 pathnames.erase(pathnames.begin());
1975 int i = 0;
1976 for (const auto& it : pathnames) {
1977 out << "declare library_path" << to_string(i++) << " \"" << it << "\";" << endl;
1978 }
1979
1980 printDeclareHeader(out);
1981 out << "process = " << boxpp(gGlobal->gProcessTree) << ';' << endl;
1982 return out.str();
1983 }
1984
createFactoryAux(const char * name,const char * dsp_content,int argc,const char * argv[],bool generate)1985 static void createFactoryAux(const char* name, const char* dsp_content, int argc, const char* argv[], bool generate)
1986 {
1987 /****************************************************************
1988 1 - process command line
1989 *****************************************************************/
1990 initFaustDirectories(argc, argv);
1991 processCmdline(argc, argv);
1992
1993 if (gGlobal->gHelpSwitch) {
1994 printHelp();
1995 throw faustexception("");
1996 }
1997 if (gGlobal->gVersionSwitch) {
1998 printVersion();
1999 throw faustexception("");
2000 }
2001 if (gGlobal->gLibDirSwitch) {
2002 printLibDir();
2003 throw faustexception("");
2004 }
2005 if (gGlobal->gIncludeDirSwitch) {
2006 printIncludeDir();
2007 throw faustexception("");
2008 }
2009 if (gGlobal->gArchDirSwitch) {
2010 printArchDir();
2011 throw faustexception("");
2012 }
2013 if (gGlobal->gDspDirSwitch) {
2014 printDspDir();
2015 throw faustexception("");
2016 }
2017 if (gGlobal->gPathListSwitch) {
2018 printPaths();
2019 throw faustexception("");
2020 }
2021
2022 faust_alarm(gGlobal->gTimeout);
2023
2024 /****************************************************************
2025 1.5 - Check and open some input files
2026 *****************************************************************/
2027 // Check for injected code (before checking for architectures)
2028 if (gGlobal->gInjectFlag) {
2029 injcode = unique_ptr<ifstream>(new ifstream());
2030 injcode->open(gGlobal->gInjectFile.c_str(), ifstream::in);
2031 if (!injcode->is_open()) {
2032 stringstream error;
2033 error << "ERROR : can't inject \"" << gGlobal->gInjectFile << "\" external code file, file not found"
2034 << endl;
2035 throw faustexception(error.str());
2036 }
2037 }
2038
2039 /****************************************************************
2040 2 - parse source files
2041 *****************************************************************/
2042 if (dsp_content) {
2043 gGlobal->gInputString = dsp_content;
2044 gGlobal->gInputFiles.push_back(name);
2045 }
2046 initDocumentNames();
2047 initFaustFloat();
2048
2049 parseSourceFiles();
2050
2051 /****************************************************************
2052 3 - evaluate 'process' definition
2053 *****************************************************************/
2054
2055 callFun(threadEvaluateBlockDiagram); // In a thread with more stack size...
2056 if (!gGlobal->gProcessTree) {
2057 throw faustexception(gGlobal->gErrorMessage);
2058 }
2059 Tree process = gGlobal->gProcessTree;
2060 int numInputs = gGlobal->gNumInputs;
2061 int numOutputs = gGlobal->gNumOutputs;
2062
2063 if (gGlobal->gExportDSP) {
2064 string outpath =
2065 (gGlobal->gOutputDir != "") ? (gGlobal->gOutputDir + "/" + gGlobal->gOutputFile) : gGlobal->gOutputFile;
2066 ofstream out(outpath.c_str());
2067
2068 // Encode compilation options as a 'declare' : has to be located first in the string
2069 out << COMPILATION_OPTIONS << reorganizeCompilationOptions(argc, argv) << ';' << endl;
2070
2071 // Encode all libraries paths as 'declare'
2072 vector<string> pathnames = gGlobal->gReader.listSrcFiles();
2073 // Remove DSP filename
2074 pathnames.erase(pathnames.begin());
2075 int i = 0;
2076 for (const auto& it : pathnames) {
2077 out << "declare library_path" << to_string(i++) << " \"" << it << "\";" << endl;
2078 }
2079
2080 printDeclareHeader(out);
2081 out << "process = " << boxpp(process) << ";" << endl;
2082 return;
2083 }
2084
2085 /****************************************************************
2086 4 - compute output signals of 'process'
2087 *****************************************************************/
2088 startTiming("propagation");
2089
2090 callFun(threadBoxPropagateSig); // In a thread with more stack size...
2091 if (!gGlobal->gLsignalsTree) {
2092 throw faustexception(gGlobal->gErrorMessage);
2093 }
2094 Tree lsignals = gGlobal->gLsignalsTree;
2095
2096 if (gGlobal->gDetailsSwitch) {
2097 cout << "output signals are : " << endl;
2098 printSignal(lsignals, stdout);
2099 cout << "\n\n";
2100 }
2101
2102 endTiming("propagation");
2103
2104 /*************************************************************************
2105 5 - preparation of the signal tree and translate output signals
2106 **************************************************************************/
2107 generateCode(lsignals, numInputs, numOutputs, generate);
2108
2109 /****************************************************************
2110 6 - generate xml description, documentation or dot files
2111 *****************************************************************/
2112 generateOutputFiles();
2113 }
2114
createFactoryAux(const char * name,Tree signals,int argc,const char * argv[],int numInputs,int numOutputs,bool generate)2115 static void createFactoryAux(const char* name, Tree signals, int argc, const char* argv[], int numInputs, int numOutputs, bool generate)
2116 {
2117 /****************************************************************
2118 1 - process command line
2119 *****************************************************************/
2120 initFaustDirectories(argc, argv);
2121 processCmdline(argc, argv);
2122
2123 initDocumentNames();
2124 initFaustFloat();
2125
2126 /*************************************************************************
2127 5 - preparation of the signal tree and translate output signals
2128 **************************************************************************/
2129
2130 gGlobal->gMetaDataSet[tree("name")].insert(tree(quote(name)));
2131 generateCode(signals, numInputs, numOutputs, generate);
2132 }
2133
2134 // ============
2135 // Backend API
2136 // ============
2137
createFactory(const char * name,const char * dsp_content,int argc,const char * argv[],string & error_msg,bool generate)2138 dsp_factory_base* createFactory(const char* name, const char* dsp_content,
2139 int argc, const char* argv[],
2140 string& error_msg, bool generate)
2141 {
2142 gGlobal = nullptr;
2143 dsp_factory_base* factory = nullptr;
2144
2145 try {
2146 global::allocate();
2147 createFactoryAux(name, dsp_content, argc, argv, generate);
2148 error_msg = gGlobal->gErrorMsg;
2149 factory = gGlobal->gDSPFactory;
2150 } catch (faustexception& e) {
2151 error_msg = e.Message();
2152 }
2153
2154 global::destroy();
2155 return factory;
2156 }
2157
createFactory(const char * name,tvec signals,int argc,const char * argv[],std::string & error_msg)2158 dsp_factory_base* createFactory(const char* name, tvec signals,
2159 int argc, const char* argv[],
2160 std::string& error_msg)
2161 {
2162 dsp_factory_base* factory = nullptr;
2163
2164 try {
2165 createFactoryAux(name, listConvert(signals), argc, argv, gGlobal->gMaxInputs, signals.size(), true);
2166 error_msg = gGlobal->gErrorMsg;
2167 factory = gGlobal->gDSPFactory;
2168 } catch (faustexception& e) {
2169 error_msg = e.Message();
2170 }
2171
2172 return factory;
2173 }
2174
expandDSP(int argc,const char * argv[],const char * name,const char * dsp_content,string & sha_key,string & error_msg)2175 string expandDSP(int argc, const char* argv[], const char* name, const char* dsp_content, string& sha_key,
2176 string& error_msg)
2177 {
2178 gGlobal = nullptr;
2179 string res = "";
2180
2181 try {
2182 global::allocate();
2183 res = expandDSPInternal(argc, argv, name, dsp_content);
2184 sha_key = generateSHA1(res);
2185 error_msg = gGlobal->gErrorMsg;
2186 } catch (faustexception& e) {
2187 error_msg = e.Message();
2188 }
2189
2190 global::destroy();
2191 return res;
2192 }
2193
2194 // ===============
2195 // Signal C++ API
2196 // ===============
2197
createCPPDSPFactoryFromSignals(const std::string & name_app,tvec signals,int argc,const char * argv[],std::string & error_msg)2198 EXPORT dsp_factory_base* createCPPDSPFactoryFromSignals(const std::string& name_app, tvec signals,
2199 int argc, const char* argv[],
2200 std::string& error_msg)
2201 {
2202 dsp_factory_base* factory = nullptr;
2203
2204 int argc1 = 0;
2205 const char* argv1[64];
2206 argv1[argc1++] = "faust";
2207 argv1[argc1++] = "-o";
2208 argv1[argc1++] = "string";
2209
2210 // Copy arguments
2211 for (int i = 0; i < argc; i++) {
2212 argv1[argc1++] = argv[i];
2213 }
2214 argv1[argc1] = nullptr; // NULL terminated argv
2215
2216 try {
2217 createFactoryAux(name_app.c_str(), listConvert(signals), argc1, argv1, gGlobal->gMaxInputs, signals.size(), true);
2218 error_msg = gGlobal->gErrorMsg;
2219 factory = gGlobal->gDSPFactory;
2220 } catch (faustexception& e) {
2221 error_msg = e.Message();
2222 }
2223
2224 return factory;
2225 }
2226
2227 // Foreign
2228
sigFFun(Tree ff,tvec largs)2229 EXPORT Tree sigFFun(Tree ff, tvec largs)
2230 {
2231 return sigFFun(ff, listConvert(largs));
2232 }
2233
2234 enum SType { kSInt, kSReal };
2235
sigFConst(SType type,const string & name,const string & file)2236 EXPORT Tree sigFConst(SType type, const string& name, const string& file)
2237 {
2238 return sigFConst(tree(type), tree(name), tree(file));
2239 }
2240
sigFVar(SType type,const string & name,const string & file)2241 EXPORT Tree sigFVar(SType type, const string& name, const string& file)
2242 {
2243 return sigFVar(tree(type), tree(name), tree(file));
2244 }
2245
2246 // User Interface
2247
sigButton(const std::string & label)2248 EXPORT Tree sigButton(const std::string& label)
2249 {
2250 return sigButton(normalizePath(cons(tree(label), gGlobal->nil)));
2251 }
2252
sigCheckbox(const std::string & label)2253 EXPORT Tree sigCheckbox(const std::string& label)
2254 {
2255 return sigCheckbox(normalizePath(cons(tree(label), gGlobal->nil)));
2256 }
2257
sigVSlider(const std::string & label,Tree cur,Tree min,Tree max,Tree step)2258 EXPORT Tree sigVSlider(const std::string& label, Tree cur, Tree min, Tree max, Tree step)
2259 {
2260 return sigVSlider(normalizePath(cons(tree(label), gGlobal->nil)), cur, min, max, step);
2261 }
2262
sigHSlider(const std::string & label,Tree cur,Tree min,Tree max,Tree step)2263 EXPORT Tree sigHSlider(const std::string& label, Tree cur, Tree min, Tree max, Tree step)
2264 {
2265 return sigHSlider(normalizePath(cons(tree(label), gGlobal->nil)), cur, min, max, step);
2266 }
2267
sigNumEntry(const std::string & label,Tree cur,Tree min,Tree max,Tree step)2268 EXPORT Tree sigNumEntry(const std::string& label, Tree cur, Tree min, Tree max, Tree step)
2269 {
2270 return sigNumEntry(normalizePath(cons(tree(label), gGlobal->nil)), cur, min, max, step);
2271 }
2272
sigVBargraph(const std::string & label,Tree min,Tree max,Tree x)2273 EXPORT Tree sigVBargraph(const std::string& label, Tree min, Tree max, Tree x)
2274 {
2275 return sigVBargraph(normalizePath(cons(tree(label), gGlobal->nil)), min, max, x);
2276 }
2277
sigHBargraph(const std::string & label,Tree min,Tree max,Tree x)2278 EXPORT Tree sigHBargraph(const std::string& label, Tree min, Tree max, Tree x)
2279 {
2280 return sigHBargraph(normalizePath(cons(tree(label), gGlobal->nil)), min, max, x);
2281 }
2282
sigSoundfile(const std::string & label)2283 EXPORT Tree sigSoundfile(const std::string& label)
2284 {
2285 return sigSoundfile(normalizePath(cons(tree(label), gGlobal->nil)));
2286 }
2287
sigSelf()2288 EXPORT Tree sigSelf()
2289 {
2290 return sigDelay1(sigProj(0, ref(1)));
2291 }
2292
2293 //Tree liftn(Tree t, int threshold);
2294
sigRecursion(Tree s)2295 EXPORT Tree sigRecursion(Tree s)
2296 {
2297 //return sigDelay0(sigProj(0, rec(cons(liftn(s, 0), gGlobal->nil))));
2298 return sigDelay0(sigProj(0, rec(cons(s, gGlobal->nil))));
2299 }
2300
2301 // Global context, to be used in C and C++ API
2302
createLibContext()2303 extern "C" EXPORT void createLibContext()
2304 {
2305 gGlobal = nullptr;
2306 global::allocate();
2307 }
2308
destroyLibContext()2309 extern "C" EXPORT void destroyLibContext()
2310 {
2311 global::destroy();
2312 }
2313
2314 // =============
2315 // Signal C API
2316 // =============
2317
2318 #ifdef __cplusplus
2319 extern "C"
2320 {
2321 #endif
2322
CsigInt(int n)2323 EXPORT Tree CsigInt(int n)
2324 {
2325 return sigInt(n);
2326 }
2327
CsigReal(double n)2328 EXPORT Tree CsigReal(double n)
2329 {
2330 return sigReal(n);
2331 }
2332
CsigInput(int idx)2333 EXPORT Tree CsigInput(int idx)
2334 {
2335 return sigInput(idx);
2336 }
2337
CsigDelay(Tree t0,Tree del)2338 EXPORT Tree CsigDelay(Tree t0, Tree del)
2339 {
2340 return sigDelay(t0, del);
2341 }
2342
CsigIntCast(Tree s)2343 EXPORT Tree CsigIntCast(Tree s)
2344 {
2345 return sigIntCast(s);
2346 }
2347
CsigFloatCast(Tree s)2348 EXPORT Tree CsigFloatCast(Tree s)
2349 {
2350 return sigFloatCast(s);
2351 }
2352
CsigReadOnlyTable(Tree n,Tree init,Tree ridx)2353 EXPORT Tree CsigReadOnlyTable(Tree n, Tree init, Tree ridx)
2354 {
2355 return sigReadOnlyTable(n, init, ridx);
2356 }
2357
CsigWriteReadTable(Tree n,Tree init,Tree widx,Tree wsig,Tree ridx)2358 EXPORT Tree CsigWriteReadTable(Tree n, Tree init, Tree widx, Tree wsig, Tree ridx)
2359 {
2360 return sigWriteReadTable(n, init, widx, wsig,ridx);
2361 }
2362
CsigWaveform(Tree * wf_aux)2363 EXPORT Tree CsigWaveform(Tree* wf_aux)
2364 {
2365 tvec wf;
2366 int i = 0;
2367 while (wf_aux[i]) { wf.push_back(wf_aux[i]); i++; }
2368 return sigWaveform(wf);
2369 }
2370
CsigSoundfile(const char * label)2371 EXPORT Tree CsigSoundfile(const char* label)
2372 {
2373 return sigSoundfile(label);
2374 }
2375
CsigSoundfileLength(Tree sf,Tree part)2376 EXPORT Tree CsigSoundfileLength(Tree sf, Tree part)
2377 {
2378 return sigSoundfileLength(sf, part);
2379 }
2380
CsigSoundfileRate(Tree sf,Tree part)2381 EXPORT Tree CsigSoundfileRate(Tree sf, Tree part)
2382 {
2383 return sigSoundfileRate(sf, part);
2384 }
2385
CsigSoundfileBuffer(Tree sf,Tree chan,Tree part,Tree ridx)2386 EXPORT Tree CsigSoundfileBuffer(Tree sf, Tree chan, Tree part, Tree ridx)
2387 {
2388 return sigSoundfileBuffer(sf, chan, part, ridx);
2389 }
2390
CsigSelect2(Tree selector,Tree s1,Tree s2)2391 EXPORT Tree CsigSelect2(Tree selector, Tree s1, Tree s2)
2392 {
2393 return sigSelect2(selector, s1, s2);
2394 }
2395
CsigSelect3(Tree selector,Tree s1,Tree s2,Tree s3)2396 EXPORT Tree CsigSelect3(Tree selector, Tree s1, Tree s2, Tree s3)
2397 {
2398 return sigSelect3(selector, s1, s2, s3);
2399 }
2400
CsigFConst(SType type,const char * name,const char * file)2401 EXPORT Tree CsigFConst(SType type, const char* name, const char* file)
2402 {
2403 return sigFConst(type, name, file);
2404 }
2405
CsigFVar(SType type,const char * name,const char * file)2406 EXPORT Tree CsigFVar(SType type, const char* name, const char* file)
2407 {
2408 return sigFVar(type, name, file);
2409 }
2410
CsigBinOp(SOperator op,Tree x,Tree y)2411 EXPORT Tree CsigBinOp(SOperator op, Tree x, Tree y)
2412 {
2413 return sigBinOp(op, x, y);
2414 }
2415
CsigAdd(Tree x,Tree y)2416 EXPORT Tree CsigAdd(Tree x, Tree y)
2417 {
2418 return sigAdd(x, y);
2419 }
CsigSub(Tree x,Tree y)2420 EXPORT Tree CsigSub(Tree x, Tree y)
2421 {
2422 return sigSub(x, y);
2423 }
CsigMul(Tree x,Tree y)2424 EXPORT Tree CsigMul(Tree x, Tree y)
2425 {
2426 return sigMul(x, y);
2427 }
CsigDiv(Tree x,Tree y)2428 EXPORT Tree CsigDiv(Tree x, Tree y)
2429 {
2430 return sigDiv(x, y);
2431 }
CsigRem(Tree x,Tree y)2432 EXPORT Tree CsigRem(Tree x, Tree y)
2433 {
2434 return sigRem(x, y);
2435 }
2436
CsigLeftShift(Tree x,Tree y)2437 EXPORT Tree CsigLeftShift(Tree x, Tree y)
2438 {
2439 return sigLeftShift(x, y);
2440 }
CsigLRightShift(Tree x,Tree y)2441 EXPORT Tree CsigLRightShift(Tree x, Tree y)
2442 {
2443 return sigLRightShift(x, y);
2444 }
CsigARightShift(Tree x,Tree y)2445 EXPORT Tree CsigARightShift(Tree x, Tree y)
2446 {
2447 return sigARightShift(x, y);
2448 }
2449
CsigGT(Tree x,Tree y)2450 EXPORT Tree CsigGT(Tree x, Tree y)
2451 {
2452 return sigGT(x, y);
2453 }
CsigLT(Tree x,Tree y)2454 EXPORT Tree CsigLT(Tree x, Tree y)
2455 {
2456 return sigLT(x, y);
2457 }
CsigGE(Tree x,Tree y)2458 EXPORT Tree CsigGE(Tree x, Tree y)
2459 {
2460 return sigGE(x, y);
2461 }
CsigLE(Tree x,Tree y)2462 EXPORT Tree CsigLE(Tree x, Tree y)
2463 {
2464 return sigLE(x, y);
2465 }
CsigEQ(Tree x,Tree y)2466 EXPORT Tree CsigEQ(Tree x, Tree y)
2467 {
2468 return sigEQ(x, y);
2469 }
CsigNE(Tree x,Tree y)2470 EXPORT Tree CsigNE(Tree x, Tree y)
2471 {
2472 return sigNE(x, y);
2473 }
2474
CsigAND(Tree x,Tree y)2475 EXPORT Tree CsigAND(Tree x, Tree y)
2476 {
2477 return sigAND(x, y);
2478 }
CsigOR(Tree x,Tree y)2479 EXPORT Tree CsigOR(Tree x, Tree y)
2480 {
2481 return sigOR(x, y);
2482 }
CsigXOR(Tree x,Tree y)2483 EXPORT Tree CsigXOR(Tree x, Tree y)
2484 {
2485 return sigXOR(x, y);
2486 }
2487
CsigAbs(Tree x)2488 EXPORT Tree CsigAbs(Tree x)
2489 {
2490 return sigAbs(x);
2491 }
CsigAcos(Tree x)2492 EXPORT Tree CsigAcos(Tree x)
2493 {
2494 return sigAcos(x);
2495 }
CsigTan(Tree x)2496 EXPORT Tree CsigTan(Tree x)
2497 {
2498 return sigTan(x);
2499 }
CsigSqrt(Tree x)2500 EXPORT Tree CsigSqrt(Tree x)
2501 {
2502 return sigSqrt(x);
2503 }
CsigSin(Tree x)2504 EXPORT Tree CsigSin(Tree x)
2505 {
2506 return sigSin(x);
2507 }
CsigRint(Tree x)2508 EXPORT Tree CsigRint(Tree x)
2509 {
2510 return sigRint(x);
2511 }
CsigRemainder(Tree x,Tree y)2512 EXPORT Tree CsigRemainder(Tree x, Tree y)
2513 {
2514 return sigRemainder(x, y);
2515 }
CsigPow(Tree x,Tree y)2516 EXPORT Tree CsigPow(Tree x, Tree y)
2517 {
2518 return sigPow(x, y);
2519 }
CsigMin(Tree x,Tree y)2520 EXPORT Tree CsigMin(Tree x, Tree y)
2521 {
2522 return sigMin(x, y);
2523 }
CsigMax(Tree x,Tree y)2524 EXPORT Tree CsigMax(Tree x, Tree y)
2525 {
2526 return sigMax(x, y);
2527 }
CsigLog(Tree x)2528 EXPORT Tree CsigLog(Tree x)
2529 {
2530 return sigLog(x);
2531 }
CsigLog10(Tree x)2532 EXPORT Tree CsigLog10(Tree x)
2533 {
2534 return sigLog10(x);
2535 }
CsigFmod(Tree x,Tree y)2536 EXPORT Tree CsigFmod(Tree x, Tree y)
2537 {
2538 return sigFmod(x, y);
2539 }
CsigFloor(Tree x)2540 EXPORT Tree CsigFloor(Tree x)
2541 {
2542 return sigFloor(x);
2543 }
CsigExp(Tree x)2544 EXPORT Tree CsigExp(Tree x)
2545 {
2546 return sigExp(x);
2547 }
CsigExp10(Tree x)2548 EXPORT Tree CsigExp10(Tree x)
2549 {
2550 return sigExp10(x);
2551 }
CsigCos(Tree x)2552 EXPORT Tree CsigCos(Tree x)
2553 {
2554 return sigCos(x);
2555 }
CsigCeil(Tree x)2556 EXPORT Tree CsigCeil(Tree x)
2557 {
2558 return sigCeil(x);
2559 }
CsigAtan(Tree x)2560 EXPORT Tree CsigAtan(Tree x)
2561 {
2562 return sigAtan(x);
2563 }
CsigAtan2(Tree x,Tree y)2564 EXPORT Tree CsigAtan2(Tree x, Tree y)
2565 {
2566 return sigAtan2(x, y);
2567 }
CsigAsin(Tree x)2568 EXPORT Tree CsigAsin(Tree x)
2569 {
2570 return sigAsin(x);
2571 }
2572
CsigSelf()2573 EXPORT Tree CsigSelf()
2574 {
2575 return sigSelf();
2576 }
2577
CsigRecursion(Tree s1)2578 EXPORT Tree CsigRecursion(Tree s1)
2579 {
2580 return sigRecursion(s1);
2581 }
2582
CsigButton(const char * label)2583 EXPORT Tree CsigButton(const char* label)
2584 {
2585 return sigButton(label);
2586 }
2587
CsigCheckbox(const char * label)2588 EXPORT Tree CsigCheckbox(const char* label)
2589 {
2590 return sigCheckbox(label);
2591 }
2592
CsigVSlider(const char * label,Tree init,Tree min,Tree max,Tree step)2593 EXPORT Tree CsigVSlider(const char* label, Tree init, Tree min, Tree max, Tree step)
2594 {
2595 return sigVSlider(label, init, min, max, step);
2596 }
2597
CsigHSlider(const char * label,Tree init,Tree min,Tree max,Tree step)2598 EXPORT Tree CsigHSlider(const char* label, Tree init, Tree min, Tree max, Tree step)
2599 {
2600 return sigHSlider(label, init, min, max, step);
2601 }
2602
CsigNumEntry(const char * label,Tree init,Tree min,Tree max,Tree step)2603 EXPORT Tree CsigNumEntry(const char* label, Tree init, Tree min, Tree max, Tree step)
2604 {
2605 return sigNumEntry(label, init, min, max, step);
2606 }
2607
CsigVBargraph(const char * label,Tree min,Tree max,Tree x)2608 EXPORT Tree CsigVBargraph(const char* label, Tree min, Tree max, Tree x)
2609 {
2610 return sigVBargraph(label, min, max, x);
2611 }
2612
CsigHBargraph(const char * label,Tree min,Tree max,Tree x)2613 EXPORT Tree CsigHBargraph(const char* label, Tree min, Tree max, Tree x)
2614 {
2615 return sigHBargraph(label, min, max, x);
2616 }
2617
CsigAttach(Tree x,Tree y)2618 EXPORT Tree CsigAttach(Tree x, Tree y)
2619 {
2620 return sigAttach(y, y);
2621 }
2622
2623 #ifdef __cplusplus
2624 }
2625 #endif
2626
2627 // ============
2628 // Box C++ API
2629 // ============
2630
2631 // Can generate faustexception
boxesToSignalsAux(Tree box)2632 tvec boxesToSignalsAux(Tree box)
2633 {
2634 int numInputs, numOutputs;
2635
2636 if (!getBoxType(box, &numInputs, &numOutputs)) {
2637 stringstream error;
2638 error << "ERROR during the evaluation of process : " << boxpp(box) << endl;
2639 throw faustexception(error.str());
2640 }
2641
2642 return propagate(gGlobal->nil, gGlobal->nil, box, makeSigInputList(numInputs));
2643 }
2644
boxesToSignals(Tree box,std::string & error_msg)2645 EXPORT tvec boxesToSignals(Tree box, std::string& error_msg)
2646 {
2647 try {
2648 return boxesToSignalsAux(box);
2649 } catch (faustexception& e) {
2650 error_msg = e.Message();
2651 return {};
2652 }
2653 }
2654
createCPPDSPFactoryFromBoxes(const std::string & name_app,Tree box,int argc,const char * argv[],std::string & error_msg)2655 EXPORT dsp_factory_base* createCPPDSPFactoryFromBoxes(const std::string& name_app,
2656 Tree box,
2657 int argc, const char* argv[],
2658 std::string& error_msg)
2659 {
2660 try {
2661 tvec signals = boxesToSignalsAux(box);
2662 return createCPPDSPFactoryFromSignals(name_app, signals, argc, argv, error_msg);
2663 } catch (faustexception& e) {
2664 error_msg = e.Message();
2665 return nullptr;
2666 }
2667 }
2668
boxDelay()2669 EXPORT Tree boxDelay()
2670 {
2671 return boxPrim2(sigDelay);
2672 }
2673
boxIntCast()2674 EXPORT Tree boxIntCast()
2675 {
2676 return boxPrim1(sigIntCast);
2677 }
2678
boxFloatCast()2679 EXPORT Tree boxFloatCast()
2680 {
2681 return boxPrim1(sigFloatCast);
2682 }
2683
boxReadOnlyTable()2684 EXPORT Tree boxReadOnlyTable()
2685 {
2686 return boxPrim3(sigReadOnlyTable);
2687 }
2688
boxWriteReadTable()2689 EXPORT Tree boxWriteReadTable()
2690 {
2691 return boxPrim5(sigWriteReadTable);
2692 }
2693
boxSoundfile(const std::string & label,Tree chan)2694 EXPORT Tree boxSoundfile(const std::string& label, Tree chan)
2695 {
2696 return boxSoundfile(tree(label), chan);
2697 }
2698
boxSelect2()2699 EXPORT Tree boxSelect2()
2700 {
2701 return boxPrim3(sigSelect2);
2702 }
2703
boxSelect3()2704 EXPORT Tree boxSelect3()
2705 {
2706 return boxPrim4(sigSelect3);
2707 }
2708
boxFConst(SType type,const std::string & name,const std::string & file)2709 EXPORT Tree boxFConst(SType type, const std::string& name, const std::string& file)
2710 {
2711 return boxFConst(tree(type), tree(name), tree(file));
2712 }
2713
boxFVar(SType type,const std::string & name,const std::string & file)2714 EXPORT Tree boxFVar(SType type, const std::string& name, const std::string& file)
2715 {
2716 return boxFVar(tree(type), tree(name), tree(file));
2717 }
2718
boxBinOp(SOperator op)2719 EXPORT Tree boxBinOp(SOperator op)
2720 {
2721 static sigFun fun [] = {
2722 sigAdd, sigSub, sigMul, sigDiv, sigRem,
2723 sigLeftShift, sigLRightShift, sigARightShift,
2724 sigGT, sigLT, sigGE, sigLE, sigEQ, sigNE,
2725 sigAND, sigOR, sigXOR
2726 };
2727 faustassert(op >= kAdd && op <= kXOR);
2728 return boxPrim2(fun[op]);
2729 }
2730
2731 // Specific binary mathematical functions
2732
boxAdd()2733 EXPORT Tree boxAdd()
2734 {
2735 return boxPrim2(sigAdd);
2736 }
boxSub()2737 EXPORT Tree boxSub()
2738 {
2739 return boxPrim2(sigSub);
2740 }
boxMul()2741 EXPORT Tree boxMul()
2742 {
2743 return boxPrim2(sigMul);
2744 }
boxDiv()2745 EXPORT Tree boxDiv()
2746 {
2747 return boxPrim2(sigDiv);
2748 }
boxRem()2749 EXPORT Tree boxRem()
2750 {
2751 return boxPrim2(sigRem);
2752 }
2753
boxLeftShift()2754 EXPORT Tree boxLeftShift()
2755 {
2756 return boxPrim2(sigLeftShift);
2757 }
boxLRightShift()2758 EXPORT Tree boxLRightShift()
2759 {
2760 return boxPrim2(sigLRightShift);
2761 }
boxARightShift()2762 EXPORT Tree boxARightShift()
2763 {
2764 return boxPrim2(sigARightShift);
2765 }
2766
boxGT()2767 EXPORT Tree boxGT()
2768 {
2769 return boxPrim2(sigGT);
2770 }
boxLT()2771 EXPORT Tree boxLT()
2772 {
2773 return boxPrim2(sigLT);
2774 }
boxGE()2775 EXPORT Tree boxGE()
2776 {
2777 return boxPrim2(sigGE);
2778 }
boxLE()2779 EXPORT Tree boxLE()
2780 {
2781 return boxPrim2(sigLE);
2782 }
boxEQ()2783 EXPORT Tree boxEQ()
2784 {
2785 return boxPrim2(sigEQ);
2786 }
boxNE()2787 EXPORT Tree boxNE()
2788 {
2789 return boxPrim2(sigNE);
2790 }
2791
boxAND()2792 EXPORT Tree boxAND()
2793 {
2794 return boxPrim2(sigAND);
2795 }
boxOR()2796 EXPORT Tree boxOR()
2797 {
2798 return boxPrim2(sigOR);
2799 }
boxXOR()2800 EXPORT Tree boxXOR()
2801 {
2802 return boxPrim2(sigXOR);
2803 }
2804
2805 // Extended unary of binary mathematical functions
2806
boxAbs()2807 EXPORT Tree boxAbs()
2808 {
2809 return gGlobal->gAbsPrim->box();
2810 }
boxAcos()2811 EXPORT Tree boxAcos()
2812 {
2813 return gGlobal->gAcosPrim->box();
2814 }
boxTan()2815 EXPORT Tree boxTan()
2816 {
2817 return gGlobal->gTanPrim->box();
2818 }
boxSqrt()2819 EXPORT Tree boxSqrt()
2820 {
2821 return gGlobal->gSqrtPrim->box();
2822 }
boxSin()2823 EXPORT Tree boxSin()
2824 {
2825 return gGlobal->gSinPrim->box();
2826 }
boxRint()2827 EXPORT Tree boxRint()
2828 {
2829 return gGlobal->gRintPrim->box();
2830 }
boxRemainder()2831 EXPORT Tree boxRemainder()
2832 {
2833 return gGlobal->gRemainderPrim->box();
2834 }
boxPow()2835 EXPORT Tree boxPow()
2836 {
2837 return gGlobal->gPowPrim->box();
2838 }
boxMin()2839 EXPORT Tree boxMin()
2840 {
2841 return gGlobal->gMinPrim->box();
2842 }
boxMax()2843 EXPORT Tree boxMax()
2844 {
2845 return gGlobal->gMaxPrim->box();
2846 }
boxLog()2847 EXPORT Tree boxLog()
2848 {
2849 return gGlobal->gLogPrim->box();
2850 }
boxLog10()2851 EXPORT Tree boxLog10()
2852 {
2853 return gGlobal->gLog10Prim->box();
2854 }
boxFmod()2855 EXPORT Tree boxFmod()
2856 {
2857 return gGlobal->gAbsPrim->box();
2858 }
boxFloor()2859 EXPORT Tree boxFloor()
2860 {
2861 return gGlobal->gFloorPrim->box();
2862 }
boxExp()2863 EXPORT Tree boxExp()
2864 {
2865 return gGlobal->gExpPrim->box();
2866 }
boxExp10()2867 EXPORT Tree boxExp10()
2868 {
2869 return gGlobal->gExp10Prim->box();
2870 }
boxCos()2871 EXPORT Tree boxCos()
2872 {
2873 return gGlobal->gAbsPrim->box();
2874 }
boxCeil()2875 EXPORT Tree boxCeil()
2876 {
2877 return gGlobal->gCeilPrim->box();
2878 }
boxAtan()2879 EXPORT Tree boxAtan()
2880 {
2881 return gGlobal->gAtanPrim->box();
2882 }
boxAtan2()2883 EXPORT Tree boxAtan2()
2884 {
2885 return gGlobal->gAtan2Prim->box();
2886 }
boxAsin()2887 EXPORT Tree boxAsin()
2888 {
2889 return gGlobal->gAsinPrim->box();
2890 }
2891
2892 // User Interface
2893
boxButton(const std::string & label)2894 EXPORT Tree boxButton(const std::string& label)
2895 {
2896 return boxButton(tree(label));
2897 }
2898
boxCheckbox(const std::string & label)2899 EXPORT Tree boxCheckbox(const std::string& label)
2900 {
2901 return boxButton(tree(label));
2902 }
2903
boxVSlider(const std::string & label,Tree init,Tree min,Tree max,Tree step)2904 EXPORT Tree boxVSlider(const std::string& label, Tree init, Tree min, Tree max, Tree step)
2905 {
2906 return boxVSlider(tree(label), init, min, max, step);
2907 }
2908
boxHSlider(const std::string & label,Tree init,Tree min,Tree max,Tree step)2909 EXPORT Tree boxHSlider(const std::string& label, Tree init, Tree min, Tree max, Tree step)
2910 {
2911 return boxHSlider(tree(label), init, min, max, step);
2912 }
2913
boxNumEntry(const std::string & label,Tree init,Tree min,Tree max,Tree step)2914 EXPORT Tree boxNumEntry(const std::string& label, Tree init, Tree min, Tree max, Tree step)
2915 {
2916 return boxNumEntry(tree(label), init, min, max, step);
2917 }
2918
boxVBargraph(const std::string & label,Tree min,Tree max)2919 EXPORT Tree boxVBargraph(const std::string& label, Tree min, Tree max)
2920 {
2921 return boxVBargraph(tree(label), min, max);
2922 }
2923
boxHBargraph(const std::string & label,Tree min,Tree max)2924 EXPORT Tree boxHBargraph(const std::string& label, Tree min, Tree max)
2925 {
2926 return boxHBargraph(tree(label), min, max);
2927 }
2928
boxAttach()2929 EXPORT Tree boxAttach()
2930 {
2931 return boxPrim2(sigAttach);
2932 }
2933
2934 // Helpers
2935
boxPar3(Tree x,Tree y,Tree z)2936 EXPORT Tree boxPar3(Tree x, Tree y, Tree z)
2937 {
2938 return boxPar(x, boxPar(y, z));
2939 }
2940
boxPar4(Tree a,Tree b,Tree c,Tree d)2941 EXPORT Tree boxPar4(Tree a, Tree b, Tree c, Tree d)
2942 {
2943 return boxPar(a, boxPar3(b, c, d));
2944 }
2945
boxPar5(Tree a,Tree b,Tree c,Tree d,Tree e)2946 EXPORT Tree boxPar5(Tree a, Tree b, Tree c, Tree d, Tree e)
2947 {
2948 return boxPar(a, boxPar4(b, c, d, e));
2949 }
2950
boxDelay(Tree s,Tree del)2951 EXPORT Tree boxDelay(Tree s, Tree del)
2952 {
2953 return boxSeq(boxPar(s, del), boxDelay());
2954 }
2955
boxIntCast(Tree s)2956 EXPORT Tree boxIntCast(Tree s)
2957 {
2958 return boxSeq(s, boxIntCast());
2959 }
2960
boxFloatCast(Tree s)2961 EXPORT Tree boxFloatCast(Tree s)
2962 {
2963 return boxSeq(s, boxFloatCast());
2964 }
2965
boxReadOnlyTable(Tree n,Tree init,Tree ridx)2966 EXPORT Tree boxReadOnlyTable(Tree n, Tree init, Tree ridx)
2967 {
2968 return boxSeq(boxPar3(n, init, ridx), boxReadOnlyTable());
2969 }
2970
boxWriteReadTable(Tree n,Tree init,Tree widx,Tree wsig,Tree ridx)2971 EXPORT Tree boxWriteReadTable(Tree n, Tree init, Tree widx, Tree wsig, Tree ridx)
2972 {
2973 return boxSeq(boxPar5(n, init, widx, wsig, ridx), boxWriteReadTable());
2974 }
2975
boxSoundfile(const std::string & label,Tree chan,Tree part,Tree ridx)2976 EXPORT Tree boxSoundfile(const std::string& label, Tree chan, Tree part, Tree ridx)
2977 {
2978 return boxSeq(boxPar(part, ridx), boxSoundfile(label, chan));
2979 }
2980
boxSelect2(Tree selector,Tree s1,Tree s2)2981 EXPORT Tree boxSelect2(Tree selector, Tree s1, Tree s2)
2982 {
2983 return boxSeq(boxPar3(selector, s1, s2), boxSelect2());
2984 }
2985
boxSelect3(Tree selector,Tree s1,Tree s2,Tree s3)2986 EXPORT Tree boxSelect3(Tree selector, Tree s1, Tree s2, Tree s3)
2987 {
2988 return boxSeq(boxPar4(selector, s1, s2, s3), boxSelect3());
2989 }
2990
boxBinOp(SOperator op,Tree b1,Tree b2)2991 EXPORT Tree boxBinOp(SOperator op, Tree b1, Tree b2)
2992 {
2993 return boxSeq(boxPar(b1, b2), boxBinOp(op));
2994 }
2995
boxAdd(Tree b1,Tree b2)2996 EXPORT Tree boxAdd(Tree b1, Tree b2)
2997 {
2998 return boxSeq(boxPar(b1, b2), boxAdd());
2999 }
3000
boxSub(Tree b1,Tree b2)3001 EXPORT Tree boxSub(Tree b1, Tree b2)
3002 {
3003 return boxSeq(boxPar(b1, b2), boxSub());
3004 }
3005
boxMul(Tree b1,Tree b2)3006 EXPORT Tree boxMul(Tree b1, Tree b2)
3007 {
3008 return boxSeq(boxPar(b1, b2), boxMul());
3009 }
3010
boxDiv(Tree b1,Tree b2)3011 EXPORT Tree boxDiv(Tree b1, Tree b2)
3012 {
3013 return boxSeq(boxPar(b1, b2), boxDiv());
3014 }
3015
boxRem(Tree b1,Tree b2)3016 EXPORT Tree boxRem(Tree b1, Tree b2)
3017 {
3018 return boxSeq(boxPar(b1, b2), boxRem());
3019 }
3020
boxLeftShift(Tree b1,Tree b2)3021 EXPORT Tree boxLeftShift(Tree b1, Tree b2)
3022 {
3023 return boxSeq(boxPar(b1, b2), boxLeftShift());
3024 }
3025
boxLRightShift(Tree b1,Tree b2)3026 EXPORT Tree boxLRightShift(Tree b1, Tree b2)
3027 {
3028 return boxSeq(boxPar(b1, b2), boxLRightShift());
3029 }
3030
boxARightShift(Tree b1,Tree b2)3031 EXPORT Tree boxARightShift(Tree b1, Tree b2)
3032 {
3033 return boxSeq(boxPar(b1, b2), boxARightShift());
3034 }
3035
boxGT(Tree b1,Tree b2)3036 EXPORT Tree boxGT(Tree b1, Tree b2)
3037 {
3038 return boxSeq(boxPar(b1, b2), boxGT());
3039 }
3040
boxLT(Tree b1,Tree b2)3041 EXPORT Tree boxLT(Tree b1, Tree b2)
3042 {
3043 return boxSeq(boxPar(b1, b2), boxLT());
3044 }
3045
boxGE(Tree b1,Tree b2)3046 EXPORT Tree boxGE(Tree b1, Tree b2)
3047 {
3048 return boxSeq(boxPar(b1, b2), boxGE());
3049 }
3050
boxLE(Tree b1,Tree b2)3051 EXPORT Tree boxLE(Tree b1, Tree b2)
3052 {
3053 return boxSeq(boxPar(b1, b2), boxLE());
3054 }
3055
boxEQ(Tree b1,Tree b2)3056 EXPORT Tree boxEQ(Tree b1, Tree b2)
3057 {
3058 return boxSeq(boxPar(b1, b2), boxEQ());
3059 }
3060
boxNE(Tree b1,Tree b2)3061 EXPORT Tree boxNE(Tree b1, Tree b2)
3062 {
3063 return boxSeq(boxPar(b1, b2), boxNE());
3064 }
3065
boxAND(Tree b1,Tree b2)3066 EXPORT Tree boxAND(Tree b1, Tree b2)
3067 {
3068 return boxSeq(boxPar(b1, b2), boxAND());
3069 }
3070
boxOR(Tree b1,Tree b2)3071 EXPORT Tree boxOR(Tree b1, Tree b2)
3072 {
3073 return boxSeq(boxPar(b1, b2), boxOR());
3074 }
3075
boxXOR(Tree b1,Tree b2)3076 EXPORT Tree boxXOR(Tree b1, Tree b2)
3077 {
3078 return boxSeq(boxPar(b1, b2), boxXOR());
3079 }
3080
boxAbs(Tree x)3081 EXPORT Tree boxAbs(Tree x)
3082 {
3083 return boxSeq(x, boxAbs());
3084 }
3085
boxAcos(Tree x)3086 EXPORT Tree boxAcos(Tree x)
3087 {
3088 return boxSeq(x, boxAcos());
3089 }
3090
boxTan(Tree x)3091 EXPORT Tree boxTan(Tree x)
3092 {
3093 return boxSeq(x, boxTan());
3094 }
3095
boxSqrt(Tree x)3096 EXPORT Tree boxSqrt(Tree x)
3097 {
3098 return boxSeq(x, boxSqrt());
3099 }
3100
boxSin(Tree x)3101 EXPORT Tree boxSin(Tree x)
3102 {
3103 return boxSeq(x, boxSin());
3104 }
3105
boxRint(Tree x)3106 EXPORT Tree boxRint(Tree x)
3107 {
3108 return boxSeq(x, boxRint());
3109 }
3110
boxLog(Tree x)3111 EXPORT Tree boxLog(Tree x)
3112 {
3113 return boxSeq(x, boxLog());
3114 }
3115
boxLog10(Tree x)3116 EXPORT Tree boxLog10(Tree x)
3117 {
3118 return boxSeq(x, boxLog10());
3119 }
3120
boxFloor(Tree x)3121 EXPORT Tree boxFloor(Tree x)
3122 {
3123 return boxSeq(x, boxFloor());
3124 }
3125
boxExp(Tree x)3126 EXPORT Tree boxExp(Tree x)
3127 {
3128 return boxSeq(x, boxExp());
3129 }
3130
boxExp10(Tree x)3131 EXPORT Tree boxExp10(Tree x)
3132 {
3133 return boxSeq(x, boxExp10());
3134 }
3135
boxCos(Tree x)3136 EXPORT Tree boxCos(Tree x)
3137 {
3138 return boxSeq(x, boxCos());
3139 }
3140
boxCeil(Tree x)3141 EXPORT Tree boxCeil(Tree x)
3142 {
3143 return boxSeq(x, boxCeil());
3144 }
3145
boxAtan(Tree x)3146 EXPORT Tree boxAtan(Tree x)
3147 {
3148 return boxSeq(x, boxAtan());
3149 }
3150
boxAsin(Tree x)3151 EXPORT Tree boxAsin(Tree x)
3152 {
3153 return boxSeq(x, boxAsin());
3154 }
3155
boxRemainder(Tree b1,Tree b2)3156 EXPORT Tree boxRemainder(Tree b1, Tree b2)
3157 {
3158 return boxSeq(boxPar(b1, b2), boxRemainder());
3159 }
3160
boxPow(Tree b1,Tree b2)3161 EXPORT Tree boxPow(Tree b1, Tree b2)
3162 {
3163 return boxSeq(boxPar(b1, b2), boxPow());
3164 }
3165
boxMin(Tree b1,Tree b2)3166 EXPORT Tree boxMin(Tree b1, Tree b2)
3167 {
3168 return boxSeq(boxPar(b1, b2), boxMin());
3169 }
3170
boxMax(Tree b1,Tree b2)3171 EXPORT Tree boxMax(Tree b1, Tree b2)
3172 {
3173 return boxSeq(boxPar(b1, b2), boxMax());
3174 }
3175
boxFmod(Tree b1,Tree b2)3176 EXPORT Tree boxFmod(Tree b1, Tree b2)
3177 {
3178 return boxSeq(boxPar(b1, b2), boxFmod());
3179 }
3180
boxAtan2(Tree b1,Tree b2)3181 EXPORT Tree boxAtan2(Tree b1, Tree b2)
3182 {
3183 return boxSeq(boxPar(b1, b2), boxAtan2());
3184 }
3185
boxVBargraph(const std::string & label,Tree min,Tree max,Tree x)3186 EXPORT Tree boxVBargraph(const std::string& label, Tree min, Tree max, Tree x)
3187 {
3188 return boxSeq( x, boxVBargraph(label, min, max));
3189 }
3190
boxHBargraph(const std::string & label,Tree min,Tree max,Tree x)3191 EXPORT Tree boxHBargraph(const std::string& label, Tree min, Tree max, Tree x)
3192 {
3193 return boxSeq(x, boxHBargraph(label, min, max));
3194 }
3195
boxAttach(Tree s1,Tree s2)3196 EXPORT Tree boxAttach(Tree s1, Tree s2)
3197 {
3198 return boxSeq(boxPar(s1, s2), boxAttach());
3199 }
3200
3201 // ==========
3202 // Box C API
3203 // ==========
3204
3205 #ifdef __cplusplus
3206 extern "C"
3207 {
3208 #endif
3209
CboxesToSignals(Tree box,char * error_msg)3210 EXPORT Tree* CboxesToSignals(Tree box, char* error_msg)
3211 {
3212 string error_msg_aux;
3213 tvec signals = boxesToSignals(box, error_msg_aux);
3214 strncpy(error_msg, error_msg_aux.c_str(), 4096);
3215 if (signals.size() > 0) {
3216 Tree* res = (Tree*)malloc(sizeof(Tree) * (signals.size() + 1));
3217 size_t i;
3218 for (i = 0; i < signals.size(); i++) res[i] = signals[i];
3219 res[i] = NULL;
3220 return res;
3221 } else {
3222 return NULL;
3223 }
3224 }
3225
CboxInt(int n)3226 EXPORT Tree CboxInt(int n)
3227 {
3228 return boxInt(n);
3229 }
3230
CboxReal(double n)3231 EXPORT Tree CboxReal(double n)
3232 {
3233 return boxReal(n);
3234 }
3235
CboxWire()3236 EXPORT Tree CboxWire()
3237 {
3238 return boxWire();
3239 }
3240
CboxCut()3241 EXPORT Tree CboxCut()
3242 {
3243 return boxCut();
3244 }
3245
CboxSeq(Tree x,Tree y)3246 EXPORT Tree CboxSeq(Tree x, Tree y)
3247 {
3248 return boxSeq(x, y);
3249 }
3250
CboxPar(Tree x,Tree y)3251 EXPORT Tree CboxPar(Tree x, Tree y)
3252 {
3253 return boxPar(x, y);
3254 }
3255
CboxSplit(Tree x,Tree y)3256 EXPORT Tree CboxSplit(Tree x, Tree y)
3257 {
3258 return boxSplit(x, y);
3259 }
3260
CboxMerge(Tree x,Tree y)3261 EXPORT Tree CboxMerge(Tree x, Tree y)
3262 {
3263 return boxMerge(x, y);
3264 }
3265
CboxRec(Tree x,Tree y)3266 EXPORT Tree CboxRec(Tree x, Tree y)
3267 {
3268 return boxRec(x, y);
3269 }
3270
CboxRoute(Tree n,Tree m,Tree r)3271 EXPORT Tree CboxRoute(Tree n, Tree m, Tree r)
3272 {
3273 return boxRoute(n, m, r);
3274 }
3275
CboxDelay()3276 EXPORT Tree CboxDelay()
3277 {
3278 return boxDelay();
3279 }
3280
CboxIntCast()3281 EXPORT Tree CboxIntCast()
3282 {
3283 return boxIntCast();
3284 }
3285
CboxFloatCast()3286 EXPORT Tree CboxFloatCast()
3287 {
3288 return boxFloatCast();
3289 }
3290
CboxReadOnlyTable()3291 EXPORT Tree CboxReadOnlyTable()
3292 {
3293 return boxReadOnlyTable();
3294 }
3295
CboxWriteReadTable()3296 EXPORT Tree CboxWriteReadTable()
3297 {
3298 return boxWriteReadTable();
3299 }
3300
CboxWaveform(Tree * wf_aux)3301 EXPORT Tree CboxWaveform(Tree* wf_aux)
3302 {
3303 tvec wf;
3304 int i = 0;
3305 while (wf_aux[i]) { wf.push_back(wf_aux[i]); i++; }
3306 return boxWaveform(wf);
3307 }
3308
CboxSoundfile(const char * label,Tree chan)3309 EXPORT Tree CboxSoundfile(const char* label, Tree chan)
3310 {
3311 return boxSoundfile(label, chan);
3312 }
3313
CboxSelect2()3314 EXPORT Tree CboxSelect2()
3315 {
3316 return boxSelect2();
3317 }
3318
CboxSelect3()3319 EXPORT Tree CboxSelect3()
3320 {
3321 return boxSelect3();
3322 }
3323
CboxFConst(SType type,const char * name,const char * file)3324 EXPORT Tree CboxFConst(SType type, const char* name, const char* file)
3325 {
3326 return boxFConst(type, name, file);
3327 }
3328
CboxFVar(SType type,const char * name,const char * file)3329 EXPORT Tree CboxFVar(SType type, const char* name, const char* file)
3330 {
3331 return boxFVar(type, name, file);
3332 }
3333
CboxBinOp(SOperator op)3334 EXPORT Tree CboxBinOp(SOperator op)
3335 {
3336 return boxBinOp(op);
3337 }
3338
3339 // Specific binary mathematical functions
3340
CboxAdd()3341 EXPORT Tree CboxAdd()
3342 {
3343 return boxAdd();
3344 }
CboxSub()3345 EXPORT Tree CboxSub()
3346 {
3347 return boxSub();
3348 }
CboxMul()3349 EXPORT Tree CboxMul()
3350 {
3351 return boxMul();
3352 }
CboxDiv()3353 EXPORT Tree CboxDiv()
3354 {
3355 return boxDiv();
3356 }
CboxRem()3357 EXPORT Tree CboxRem()
3358 {
3359 return boxRem();
3360 }
3361
CboxLeftShift()3362 EXPORT Tree CboxLeftShift()
3363 {
3364 return boxLeftShift();
3365 }
CboxLRightShift()3366 EXPORT Tree CboxLRightShift()
3367 {
3368 return boxLRightShift();
3369 }
CboxARightShift()3370 EXPORT Tree CboxARightShift()
3371 {
3372 return boxARightShift();
3373 }
3374
CboxGT()3375 EXPORT Tree CboxGT()
3376 {
3377 return boxGT();
3378 }
CboxLT()3379 EXPORT Tree CboxLT()
3380 {
3381 return boxLT();
3382 }
CboxGE()3383 EXPORT Tree CboxGE()
3384 {
3385 return boxGE();
3386 }
CboxLE()3387 EXPORT Tree CboxLE()
3388 {
3389 return boxLE();
3390 }
CboxEQ()3391 EXPORT Tree CboxEQ()
3392 {
3393 return boxEQ();
3394 }
CboxNE()3395 EXPORT Tree CboxNE()
3396 {
3397 return boxNE();
3398 }
3399
CboxAND()3400 EXPORT Tree CboxAND()
3401 {
3402 return boxAND();
3403 }
CboxOR()3404 EXPORT Tree CboxOR()
3405 {
3406 return boxOR();
3407 }
CboxXOR()3408 EXPORT Tree CboxXOR()
3409 {
3410 return boxXOR();
3411 }
3412
3413 // Extended unary of binary mathematical functions
3414
CboxAbs()3415 EXPORT Tree CboxAbs()
3416 {
3417 return boxAbs();
3418 }
CboxAcos()3419 EXPORT Tree CboxAcos()
3420 {
3421 return boxAcos();
3422 }
CboxTan()3423 EXPORT Tree CboxTan()
3424 {
3425 return boxTan();
3426 }
CboxSqrt()3427 EXPORT Tree CboxSqrt()
3428 {
3429 return boxSqrt();
3430 }
CboxSin()3431 EXPORT Tree CboxSin()
3432 {
3433 return boxSin();
3434 }
CboxRint()3435 EXPORT Tree CboxRint()
3436 {
3437 return boxRint();
3438 }
CboxRemainder()3439 EXPORT Tree CboxRemainder()
3440 {
3441 return boxRemainder();
3442 }
CboxPow()3443 EXPORT Tree CboxPow()
3444 {
3445 return boxPow();
3446 }
CboxMin()3447 EXPORT Tree CboxMin()
3448 {
3449 return boxMin();
3450 }
CboxMax()3451 EXPORT Tree CboxMax()
3452 {
3453 return boxMax();
3454 }
CboxLog()3455 EXPORT Tree CboxLog()
3456 {
3457 return boxLog();
3458 }
CboxLog10()3459 EXPORT Tree CboxLog10()
3460 {
3461 return boxLog10();
3462 }
CboxFmod()3463 EXPORT Tree CboxFmod()
3464 {
3465 return boxFmod();
3466 }
CboxFloor()3467 EXPORT Tree CboxFloor()
3468 {
3469 return boxFloor();
3470 }
CboxExp()3471 EXPORT Tree CboxExp()
3472 {
3473 return boxExp();
3474 }
CboxExp10()3475 EXPORT Tree CboxExp10()
3476 {
3477 return boxExp10();
3478 }
CboxCos()3479 EXPORT Tree CboxCos()
3480 {
3481 return boxCos();
3482 }
CboxCeil()3483 EXPORT Tree CboxCeil()
3484 {
3485 return boxCeil();
3486 }
CboxAtan()3487 EXPORT Tree CboxAtan()
3488 {
3489 return boxAtan();
3490 }
CboxAtan2()3491 EXPORT Tree CboxAtan2()
3492 {
3493 return boxAtan2();
3494 }
CboxAsin()3495 EXPORT Tree CboxAsin()
3496 {
3497 return boxAsin();
3498 }
3499
3500 // User Interface
3501
CboxButton(const char * label)3502 EXPORT Tree CboxButton(const char* label)
3503 {
3504 return boxButton(label);
3505 }
3506
CboxCheckbox(const char * label)3507 EXPORT Tree CboxCheckbox(const char* label)
3508 {
3509 return boxButton(label);
3510 }
3511
CboxVSlider(const char * label,Tree init,Tree min,Tree max,Tree step)3512 EXPORT Tree CboxVSlider(const char* label, Tree init, Tree min, Tree max, Tree step)
3513 {
3514 return boxVSlider(label, init, min, max, step);
3515 }
3516
CboxHSlider(const char * label,Tree init,Tree min,Tree max,Tree step)3517 EXPORT Tree CboxHSlider(const char* label, Tree init, Tree min, Tree max, Tree step)
3518 {
3519 return boxHSlider(label, init, min, max, step);
3520 }
3521
CboxNumEntry(const char * label,Tree init,Tree min,Tree max,Tree step)3522 EXPORT Tree CboxNumEntry(const char* label, Tree init, Tree min, Tree max, Tree step)
3523 {
3524 return boxNumEntry(label, init, min, max, step);
3525 }
3526
CboxVBargraph(const char * label,Tree min,Tree max)3527 EXPORT Tree CboxVBargraph(const char* label, Tree min, Tree max)
3528 {
3529 return boxVBargraph(label, min, max);
3530 }
3531
CboxHBargraph(const char * label,Tree min,Tree max)3532 EXPORT Tree CboxHBargraph(const char* label, Tree min, Tree max)
3533 {
3534 return boxHBargraph(label, min, max);
3535 }
3536
CboxAttach()3537 EXPORT Tree CboxAttach()
3538 {
3539 return boxAttach();
3540 }
3541
3542 // Helpers
3543
CboxPar3(Tree x,Tree y,Tree z)3544 Tree CboxPar3(Tree x, Tree y, Tree z)
3545 {
3546 return CboxPar(x, CboxPar(y, z));
3547 }
3548
CboxPar4(Tree a,Tree b,Tree c,Tree d)3549 Tree CboxPar4(Tree a, Tree b, Tree c, Tree d)
3550 {
3551 return CboxPar(a, CboxPar3(b, c, d));
3552 }
3553
CboxPar5(Tree a,Tree b,Tree c,Tree d,Tree e)3554 Tree CboxPar5(Tree a, Tree b, Tree c, Tree d, Tree e)
3555 {
3556 return CboxPar(a, CboxPar4(b, c, d, e));
3557 }
3558
CboxDelayAux(Tree s,Tree del)3559 Tree CboxDelayAux(Tree s, Tree del)
3560 {
3561 return CboxSeq(CboxPar(s, del), CboxDelay());
3562 }
3563
CboxIntCastAux(Tree s)3564 Tree CboxIntCastAux(Tree s)
3565 {
3566 return CboxSeq(s, CboxIntCast());
3567 }
3568
CboxFloatCastAux(Tree s)3569 Tree CboxFloatCastAux(Tree s)
3570 {
3571 return CboxSeq(s, CboxFloatCast());
3572 }
3573
CboxReadOnlyTableAux(Tree n,Tree init,Tree ridx)3574 Tree CboxReadOnlyTableAux(Tree n, Tree init, Tree ridx)
3575 {
3576 return CboxSeq(CboxPar3(n, init, ridx), CboxReadOnlyTable());
3577 }
3578
CboxWriteReadTableAux(Tree n,Tree init,Tree widx,Tree wsig,Tree ridx)3579 Tree CboxWriteReadTableAux(Tree n, Tree init, Tree widx, Tree wsig, Tree ridx)
3580 {
3581 return CboxSeq(boxPar5(n, init, widx, wsig, ridx), CboxWriteReadTable());
3582 }
3583
CoxSoundfileAux(const char * label,Tree chan,Tree part,Tree ridx)3584 Tree CoxSoundfileAux(const char* label, Tree chan, Tree part, Tree ridx)
3585 {
3586 return CboxSeq(CboxPar(part, ridx), CboxSoundfile(label, chan));
3587 }
3588
CboxSelect2Aux(Tree selector,Tree s1,Tree s2)3589 Tree CboxSelect2Aux(Tree selector, Tree s1, Tree s2)
3590 {
3591 return CboxSeq(CboxPar3(selector, s1, s2), CboxSelect2());
3592 }
3593
CboxSelect3Aux(Tree selector,Tree s1,Tree s2,Tree s3)3594 Tree CboxSelect3Aux(Tree selector, Tree s1, Tree s2, Tree s3)
3595 {
3596 return CboxSeq(CboxPar4(selector, s1, s2, s3), CboxSelect3());
3597 }
3598
CboxBinOpAux(SOperator op,Tree b1,Tree b2)3599 Tree CboxBinOpAux(SOperator op, Tree b1, Tree b2)
3600 {
3601 return CboxSeq(CboxPar(b1, b2), CboxBinOp(op));
3602 }
3603
CboxAddAux(Tree b1,Tree b2)3604 Tree CboxAddAux(Tree b1, Tree b2)
3605 {
3606 return CboxSeq(CboxPar(b1, b2), CboxAdd());
3607 }
3608
CboxSubAux(Tree b1,Tree b2)3609 Tree CboxSubAux(Tree b1, Tree b2)
3610 {
3611 return CboxSeq(CboxPar(b1, b2), CboxSub());
3612 }
3613
CboxMulAux(Tree b1,Tree b2)3614 Tree CboxMulAux(Tree b1, Tree b2)
3615 {
3616 return CboxSeq(CboxPar(b1, b2), CboxMul());
3617 }
3618
CboxDivAux(Tree b1,Tree b2)3619 Tree CboxDivAux(Tree b1, Tree b2)
3620 {
3621 return CboxSeq(CboxPar(b1, b2), CboxDiv());
3622 }
3623
CboxRemAux(Tree b1,Tree b2)3624 Tree CboxRemAux(Tree b1, Tree b2)
3625 {
3626 return CboxSeq(CboxPar(b1, b2), CboxRem());
3627 }
3628
CboxLeftShiftAux(Tree b1,Tree b2)3629 Tree CboxLeftShiftAux(Tree b1, Tree b2)
3630 {
3631 return CboxSeq(CboxPar(b1, b2), CboxLeftShift());
3632 }
3633
CboxLRightShiftAux(Tree b1,Tree b2)3634 Tree CboxLRightShiftAux(Tree b1, Tree b2)
3635 {
3636 return CboxSeq(CboxPar(b1, b2), CboxLRightShift());
3637 }
3638
CboxARightShiftAux(Tree b1,Tree b2)3639 Tree CboxARightShiftAux(Tree b1, Tree b2)
3640 {
3641 return CboxSeq(CboxPar(b1, b2), CboxARightShift());
3642 }
3643
CboxGTAux(Tree b1,Tree b2)3644 Tree CboxGTAux(Tree b1, Tree b2)
3645 {
3646 return CboxSeq(CboxPar(b1, b2), CboxGT());
3647 }
3648
CboxLTAux(Tree b1,Tree b2)3649 Tree CboxLTAux(Tree b1, Tree b2)
3650 {
3651 return CboxSeq(CboxPar(b1, b2), CboxLT());
3652 }
3653
CboxGEAux(Tree b1,Tree b2)3654 Tree CboxGEAux(Tree b1, Tree b2)
3655 {
3656 return CboxSeq(CboxPar(b1, b2), CboxGE());
3657 }
3658
CboxLEAux(Tree b1,Tree b2)3659 Tree CboxLEAux(Tree b1, Tree b2)
3660 {
3661 return CboxSeq(CboxPar(b1, b2), CboxLE());
3662 }
3663
CboxEQAux(Tree b1,Tree b2)3664 Tree CboxEQAux(Tree b1, Tree b2)
3665 {
3666 return CboxSeq(CboxPar(b1, b2), CboxEQ());
3667 }
3668
CboxNEAux(Tree b1,Tree b2)3669 Tree CboxNEAux(Tree b1, Tree b2)
3670 {
3671 return CboxSeq(CboxPar(b1, b2), CboxNE());
3672 }
3673
CboxANDAux(Tree b1,Tree b2)3674 Tree CboxANDAux(Tree b1, Tree b2)
3675 {
3676 return CboxSeq(CboxPar(b1, b2), CboxAND());
3677 }
3678
CboxORAux(Tree b1,Tree b2)3679 Tree CboxORAux(Tree b1, Tree b2)
3680 {
3681 return CboxSeq(CboxPar(b1, b2), CboxOR());
3682 }
3683
CboxXORAux(Tree b1,Tree b2)3684 Tree CboxXORAux(Tree b1, Tree b2)
3685 {
3686 return CboxSeq(CboxPar(b1, b2), CboxXOR());
3687 }
3688
CboxAbsAux(Tree x)3689 Tree CboxAbsAux(Tree x)
3690 {
3691 return CboxSeq(x, CboxAbs());
3692 }
3693
CboxAcosAux(Tree x)3694 Tree CboxAcosAux(Tree x)
3695 {
3696 return CboxSeq(x, CboxAcos());
3697 }
3698
CboxTanAux(Tree x)3699 Tree CboxTanAux(Tree x)
3700 {
3701 return CboxSeq(x, CboxTan());
3702 }
3703
CboxSqrtAux(Tree x)3704 Tree CboxSqrtAux(Tree x)
3705 {
3706 return CboxSeq(x, CboxSqrt());
3707 }
3708
CboxSinAux(Tree x)3709 Tree CboxSinAux(Tree x)
3710 {
3711 return CboxSeq(x, CboxSin());
3712 }
3713
CboxRintAux(Tree x)3714 Tree CboxRintAux(Tree x)
3715 {
3716 return CboxSeq(x, CboxRint());
3717 }
3718
CboxLogAux(Tree x)3719 Tree CboxLogAux(Tree x)
3720 {
3721 return CboxSeq(x, CboxLog());
3722 }
3723
CboxLog10Aux(Tree x)3724 Tree CboxLog10Aux(Tree x)
3725 {
3726 return CboxSeq(x, CboxLog10());
3727 }
3728
CboxFloorAux(Tree x)3729 Tree CboxFloorAux(Tree x)
3730 {
3731 return CboxSeq(x, CboxFloor());
3732 }
3733
CboxExpAux(Tree x)3734 Tree CboxExpAux(Tree x)
3735 {
3736 return CboxSeq(x, CboxExp());
3737 }
3738
CboxExp10Aux(Tree x)3739 Tree CboxExp10Aux(Tree x)
3740 {
3741 return CboxSeq(x, CboxExp10());
3742 }
3743
CboxCosAux(Tree x)3744 Tree CboxCosAux(Tree x)
3745 {
3746 return CboxSeq(x, CboxCos());
3747 }
3748
CboxCeilAux(Tree x)3749 Tree CboxCeilAux(Tree x)
3750 {
3751 return CboxSeq(x, CboxCeil());
3752 }
3753
CboxAtanAux(Tree x)3754 Tree CboxAtanAux(Tree x)
3755 {
3756 return CboxSeq(x, CboxAtan());
3757 }
3758
CboxAsinAux(Tree x)3759 Tree CboxAsinAux(Tree x)
3760 {
3761 return CboxSeq(x, CboxAsin());
3762 }
3763
CboxRemainderAux(Tree b1,Tree b2)3764 Tree CboxRemainderAux(Tree b1, Tree b2)
3765 {
3766 return CboxSeq(CboxPar(b1, b2), CboxRemainder());
3767 }
3768
CboxPowAux(Tree b1,Tree b2)3769 Tree CboxPowAux(Tree b1, Tree b2)
3770 {
3771 return CboxSeq(CboxPar(b1, b2), CboxPow());
3772 }
3773
CboxMinAux(Tree b1,Tree b2)3774 Tree CboxMinAux(Tree b1, Tree b2)
3775 {
3776 return CboxSeq(CboxPar(b1, b2), CboxMin());
3777 }
3778
CboxMaxAux(Tree b1,Tree b2)3779 Tree CboxMaxAux(Tree b1, Tree b2)
3780 {
3781 return CboxSeq(CboxPar(b1, b2), CboxMax());
3782 }
3783
CboxFmodAux(Tree b1,Tree b2)3784 Tree CboxFmodAux(Tree b1, Tree b2)
3785 {
3786 return CboxSeq(CboxPar(b1, b2), CboxFmod());
3787 }
3788
CboxAtan2Aux(Tree b1,Tree b2)3789 Tree CboxAtan2Aux(Tree b1, Tree b2)
3790 {
3791 return CboxSeq(CboxPar(b1, b2), CboxAtan2());
3792 }
3793
CboxVBargraphAux(const char * label,Tree min,Tree max,Tree x)3794 Tree CboxVBargraphAux(const char* label, Tree min, Tree max, Tree x)
3795 {
3796 return CboxSeq(x, CboxVBargraph(label, min, max));
3797 }
3798
CboxHBargraphAux(const char * label,Tree min,Tree max,Tree x)3799 Tree CboxHBargraphAux(const char* label, Tree min, Tree max, Tree x)
3800 {
3801 return CboxSeq(x, CboxHBargraph(label, min, max));
3802 }
3803
CboxAttachAux(Tree s1,Tree s2)3804 Tree CboxAttachAux(Tree s1, Tree s2)
3805 {
3806 return CboxSeq(CboxPar(s1, s2), CboxAttach());
3807 }
3808
3809 #ifdef __cplusplus
3810 }
3811 #endif
3812