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