1 /************************************************************************
2 ************************************************************************
4 Copyright (C) 2003-2004 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.
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.
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 ************************************************************************/
22 #include "preprocess.hh"
27 /****************************************************************
29 *****************************************************************/
42 map
<Tree
, set
<Tree
> > gMetaDataSet
;
43 extern vector
<Tree
> gDocVector
;
44 extern string gDocLang
;
47 /****************************************************************
48 Command line tools and arguments
49 *****************************************************************/
52 string gFaustSuperSuperDirectory
;
53 string gFaustSuperDirectory
;
54 string gFaustDirectory
;
55 string gMasterDocument
;
56 string gMasterDirectory
;
59 Tree gExpandedDefList
;
61 //-- command line arguments
63 bool gHelpSwitch
= false;
64 bool gVersionSwitch
= false;
65 bool gDetailsSwitch
= false;
66 bool gDrawSignals
= false;
67 bool gShadowBlur
= false; // note: svg2pdf doesn't like the blur filter
68 bool gGraphSwitch
= false;
69 bool gDrawPSSwitch
= false;
70 bool gDrawSVGSwitch
= false;
71 bool gPrintXMLSwitch
= false;
72 bool gPrintDocSwitch
= false;
73 bool gLatexDocSwitch
= true; // Only LaTeX outformat is handled for the moment.
74 bool gStripDocSwitch
= false; // Strip <mdoc> content from doc listings.
75 int gBalancedSwitch
= 0;
76 int gFoldThreshold
= 25;
77 int gMaxNameSize
= 40;
78 bool gSimpleNames
= false;
79 bool gSimplifyDiagrams
= false;
80 bool gLessTempSwitch
= false;
81 int gMaxCopyDelay
= 16;
84 list
<string
> gInputFiles
;
86 bool gPatternEvalMode
= false;
88 bool gVectorSwitch
= false;
89 bool gDeepFirstSwitch
= false;
91 int gVectorLoopVariant
= 0;
93 bool gOpenMPSwitch
= false;
94 bool gOpenMPLoop
= false;
95 bool gSchedulerSwitch
= false;
96 bool gGroupTaskSwitch
= false;
98 bool gUIMacroSwitch
= false;
99 bool gDumpNorm
= false;
101 int gTimeout
= 120; // time out to abort compiler (in seconds)
105 bool gPrintFileListSwitch
= false;
107 string gClassName
= "mydsp";
109 //-- command line tools
111 static bool isCmd(const char* cmd
, const char* kw1
)
113 return (strcmp(cmd
, kw1
) == 0);
116 static bool isCmd(const char* cmd
, const char* kw1
, const char* kw2
)
118 return (strcmp(cmd
, kw1
) == 0) || (strcmp(cmd
, kw2
) == 0);
121 bool process_cmdline(int argc
, char* argv
[])
127 if (isCmd(argv
[i
], "-h", "--help")) {
131 } else if (isCmd(argv
[i
], "-v", "--version")) {
132 gVersionSwitch
= true;
135 } else if (isCmd(argv
[i
], "-d", "--details")) {
136 gDetailsSwitch
= true;
139 } else if (isCmd(argv
[i
], "-a", "--architecture")) {
140 gArchFile
= argv
[i
+1];
143 } else if (isCmd(argv
[i
], "-o")) {
144 gOutputFile
= argv
[i
+1];
147 } else if (isCmd(argv
[i
], "-ps", "--postscript")) {
148 gDrawPSSwitch
= true;
151 } else if (isCmd(argv
[i
], "-xml", "--xml")) {
152 gPrintXMLSwitch
= true;
155 } else if (isCmd(argv
[i
], "-tg", "--task-graph")) {
159 } else if (isCmd(argv
[i
], "-sg", "--signal-graph")) {
163 } else if (isCmd(argv
[i
], "-blur", "--shadow-blur")) {
167 } else if (isCmd(argv
[i
], "-svg", "--svg")) {
168 gDrawSVGSwitch
= true;
171 } else if (isCmd(argv
[i
], "-f", "--fold")) {
172 gFoldThreshold
= atoi(argv
[i
+1]);
175 } else if (isCmd(argv
[i
], "-mns", "--max-name-size")) {
176 gMaxNameSize
= atoi(argv
[i
+1]);
179 } else if (isCmd(argv
[i
], "-sn", "--simple-names")) {
183 } else if (isCmd(argv
[i
], "-lb", "--left-balanced")) {
187 } else if (isCmd(argv
[i
], "-mb", "--mid-balanced")) {
191 } else if (isCmd(argv
[i
], "-rb", "--right-balanced")) {
195 } else if (isCmd(argv
[i
], "-lt", "--less-temporaries")) {
196 gLessTempSwitch
= true;
199 } else if (isCmd(argv
[i
], "-mcd", "--max-copy-delay")) {
200 gMaxCopyDelay
= atoi(argv
[i
+1]);
203 } else if (isCmd(argv
[i
], "-sd", "--simplify-diagrams")) {
204 gSimplifyDiagrams
= true;
207 } else if (isCmd(argv
[i
], "-vec", "--vectorize")) {
208 gVectorSwitch
= true;
211 } else if (isCmd(argv
[i
], "-dfs", "--deepFirstScheduling")) {
212 gDeepFirstSwitch
= true;
215 } else if (isCmd(argv
[i
], "-vs", "--vec-size")) {
216 gVecSize
= atoi(argv
[i
+1]);
219 } else if (isCmd(argv
[i
], "-lv", "--loop-variant")) {
220 gVectorLoopVariant
= atoi(argv
[i
+1]);
223 } else if (isCmd(argv
[i
], "-omp", "--openMP")) {
224 gOpenMPSwitch
= true;
227 } else if (isCmd(argv
[i
], "-pl", "--par-loop")) {
231 } else if (isCmd(argv
[i
], "-sch", "--scheduler")) {
232 gSchedulerSwitch
= true;
235 } else if (isCmd(argv
[i
], "-g", "--groupTasks")) {
236 gGroupTaskSwitch
= true;
239 } else if (isCmd(argv
[i
], "-uim", "--user-interface-macros")) {
240 gUIMacroSwitch
= true;
243 } else if (isCmd(argv
[i
], "-t", "--timeout")) {
244 gTimeout
= atoi(argv
[i
+1]);
247 // double float options
248 } else if (isCmd(argv
[i
], "-single", "--single-precision-floats")) {
252 } else if (isCmd(argv
[i
], "-double", "--double-precision-floats")) {
256 } else if (isCmd(argv
[i
], "-quad", "--quad-precision-floats")) {
260 } else if (isCmd(argv
[i
], "-mdoc", "--mathdoc")) {
261 gPrintDocSwitch
= true;
264 } else if (isCmd(argv
[i
], "-mdlang", "--mathdoc-lang")) {
265 gDocLang
= argv
[i
+1];
268 } else if (isCmd(argv
[i
], "-stripmdoc", "--strip-mdoc-tags")) {
269 gStripDocSwitch
= true;
272 } else if (isCmd(argv
[i
], "-flist", "--file-list")) {
273 gPrintFileListSwitch
= true;
276 } else if (isCmd(argv
[i
], "-norm", "--normalized-form")) {
280 } else if (isCmd(argv
[i
], "-cn", "--class-name")) {
281 gClassName
= argv
[i
+1];
284 } else if (argv
[i
][0] != '-') {
285 if (check_file(argv
[i
])) {
286 gInputFiles
.push_back(argv
[i
]);
291 cerr
<< "faust: unrecognized option \"" << argv
[i
] <<"\"" << endl
;
297 // adjust related options
298 if (gOpenMPSwitch
|| gSchedulerSwitch
) gVectorSwitch
= true;
305 /****************************************************************
306 Help and Version information
307 *****************************************************************/
313 cout
<< "FAUST, DSP to C++ compiler, Version " << FAUSTVERSION
<< "\n";
314 cout
<< "Copyright (C) 2002-2012, GRAME - Centre National de Creation Musicale. All rights reserved. \n\n";
321 cout
<< "usage: faust [options] file1 [file2 ...]\n";
322 cout
<< "\twhere options represent zero or more compiler options \n\tand fileN represents a faust source file (.dsp extension).\n";
324 cout
<< "\noptions :\n";
325 cout
<< "---------\n";
327 cout
<< "-h \t\tprint this --help message\n";
328 cout
<< "-v \t\tprint compiler --version information\n";
329 cout
<< "-d \t\tprint compilation --details\n";
330 cout
<< "-tg \t\tprint the internal --task-graph in dot format file\n";
331 cout
<< "-sg \t\tprint the internal --signal-graph in dot format file\n";
332 cout
<< "-ps \t\tprint block-diagram --postscript file\n";
333 cout
<< "-svg \tprint block-diagram --svg file\n";
334 cout
<< "-mdoc \tprint --mathdoc of a Faust program in LaTeX format in a -mdoc directory\n";
335 cout
<< "-mdlang <l>\t\tload --mathdoc-lang <l> if translation file exists (<l> = en, fr, ...)\n";
336 cout
<< "-stripdoc \t\tapply --strip-mdoc-tags when printing Faust -mdoc listings\n";
337 cout
<< "-sd \t\ttry to further --simplify-diagrams before drawing them\n";
338 cout
<< "-f <n> \t\t--fold <n> threshold during block-diagram generation (default 25 elements) \n";
339 cout
<< "-mns <n> \t--max-name-size <n> threshold during block-diagram generation (default 40 char)\n";
340 cout
<< "-sn \t\tuse --simple-names (without arguments) during block-diagram generation\n";
341 cout
<< "-xml \t\tgenerate an --xml description file\n";
342 cout
<< "-blur \t\tadd a --shadow-blur to SVG boxes\n";
343 cout
<< "-lb \t\tgenerate --left-balanced expressions\n";
344 cout
<< "-mb \t\tgenerate --mid-balanced expressions (default)\n";
345 cout
<< "-rb \t\tgenerate --right-balanced expressions\n";
346 cout
<< "-lt \t\tgenerate --less-temporaries in compiling delays\n";
347 cout
<< "-mcd <n> \t--max-copy-delay <n> threshold between copy and ring buffer implementation (default 16 samples)\n";
348 cout
<< "-a <file> \tC++ architecture file\n";
349 cout
<< "-cn <name> \t--class-name <name> specify the name of the dsp class to be used instead of mydsp \n";
350 cout
<< "-t <sec> \t--timeout <sec>, abort compilation after <sec> seconds (default 120)\n";
351 cout
<< "-o <file> \tC++ output file\n";
352 cout
<< "-vec \t--vectorize generate easier to vectorize code\n";
353 cout
<< "-vs <n> \t--vec-size <n> size of the vector (default 32 samples)\n";
354 cout
<< "-lv <n> \t--loop-variant [0:fastest (default), 1:simple] \n";
355 cout
<< "-omp \t--openMP generate OpenMP pragmas, activates --vectorize option\n";
356 cout
<< "-pl \t--par-loop generate parallel loops in --openMP mode\n";
357 cout
<< "-sch \t--scheduler generate tasks and use a Work Stealing scheduler, activates --vectorize option\n";
358 cout
<< "-dfs \t--deepFirstScheduling schedule vector loops in deep first order\n";
359 cout
<< "-g \t\t--groupTasks group single-threaded sequential tasks together when -omp or -sch is used\n";
360 cout
<< "-uim \t--user-interface-macros add user interface macro definitions in the C++ code\n";
361 cout
<< "-single \tuse --single-precision-floats for internal computations (default)\n";
362 cout
<< "-double \tuse --double-precision-floats for internal computations\n";
363 cout
<< "-quad \t\tuse --quad-precision-floats for internal computations\n";
364 cout
<< "-flist \t\tuse --file-list used to eval process\n";
365 cout
<< "-norm \t\t--normalized-form prints signals in normalized form and exits\n";
367 cout
<< "\nexample :\n";
368 cout
<< "---------\n";
370 cout
<< "faust -a jack-gtk.cpp -o myfx.cpp myfx.dsp\n";
374 void printheader(ostream
& dst
)
376 // defines the metadata we want to print as comments at the begin of in the C++ file
377 set
<Tree
> selectedKeys
;
378 selectedKeys
.insert(tree("name"));
379 selectedKeys
.insert(tree("author"));
380 selectedKeys
.insert(tree("copyright"));
381 selectedKeys
.insert(tree("license"));
382 selectedKeys
.insert(tree("version"));
384 dst
<< "//-----------------------------------------------------" << endl
;
385 for (map
<Tree
, set
<Tree
> >::iterator i
= gMetaDataSet
.begin(); i
!= gMetaDataSet
.end(); i
++) {
386 if (selectedKeys
.count(i
->first
)) {
387 dst
<< "// " << *(i
->first
);
388 const char* sep
= ": ";
389 for (set
<Tree
>::iterator j
= i
->second
.begin(); j
!= i
->second
.end(); ++j
) {
398 dst
<< "// Code generated with Faust " << FAUSTVERSION
<< " (http://faust.grame.fr)" << endl
;
399 dst
<< "//-----------------------------------------------------" << endl
;
405 /****************************************************************
407 *****************************************************************/
412 * transform a filename "faust/example/noise.dsp" into
413 * the corresponding fx name "noise"
415 static string
fxname(const string
& filename
)
417 // determine position right after the last '/' or 0
419 for (unsigned int i
=0; i
<filename
.size(); i
++) {
420 if (filename
[i
] == '/') { p1
= i
+1; }
423 // determine position of the last '.'
424 unsigned int p2
= filename
.size();
425 for (unsigned int i
=p1
; i
<filename
.size(); i
++) {
426 if (filename
[i
] == '.') { p2
= i
; }
429 return filename
.substr(p1
, p2
-p1
);
433 static void initFaustDirectories()
436 getFaustPathname(s
, 1024);
438 gFaustDirectory
= filedirname(s
);
439 gFaustSuperDirectory
= filedirname(gFaustDirectory
);
440 gFaustSuperSuperDirectory
= filedirname(gFaustSuperDirectory
);
441 if (gInputFiles
.empty()) {
442 gMasterDocument
= "Unknown";
443 gMasterDirectory
= ".";
444 gMasterName
= "faustfx";
445 gDocName
= "faustdoc";
447 gMasterDocument
= *gInputFiles
.begin();
448 gMasterDirectory
= filedirname(gMasterDocument
);
449 gMasterName
= fxname(gMasterDocument
);
450 gDocName
= fxname(gMasterDocument
);
454 char* preProcess (char* file_route
)
457 /****************************************************************
458 1 - process command line
459 *****************************************************************/
464 argv
[2] = file_route
;
466 process_cmdline(argc
, argv
);
468 if (gHelpSwitch
) { printhelp(); exit(0); }
469 if (gVersionSwitch
) { printversion(); exit(0); }
471 initFaustDirectories();
477 /****************************************************************
478 2 - parse source files
479 *****************************************************************/
481 startTiming("parser");
484 list
<string
>::iterator s
;
488 if (gInputFiles
.begin() == gInputFiles
.end()) {
489 cerr
<< "ERROR: no files specified;" << endl
;
490 cerr
<< "interpreter <program.dsp> [input.wav]." << endl
;
493 for (s
= gInputFiles
.begin(); s
!= gInputFiles
.end(); s
++) {
494 if (s
== gInputFiles
.begin()) gMasterDocument
= *s
;
495 gResult2
= cons(importFile(tree(s
->c_str())), gResult2
);
498 //fprintf(stderr, "Erreur de parsing 2, count = %d \n", yyerr);
501 gExpandedDefList
= gReader
.expandlist(gResult2
);
505 /****************************************************************
506 3 - evaluate 'process' definition
507 *****************************************************************/
509 startTiming("evaluation");
511 Tree process
= evalprocess(gExpandedDefList
);
513 if (gErrorCount
> 0) {
514 // cerr << "Total of " << gErrorCount << " errors during evaluation of : process = " << boxpp(process) << ";\n";
515 cerr
<< "Total of " << gErrorCount
<< " errors during the compilation of " << gMasterDocument
<< ";\n";
519 endTiming("evaluation");
521 ostringstream result_stream
;
522 result_stream
<< boxpp(process
);
523 string result_string
= result_stream
.str();
524 char* result_char
= new char [result_string
.length()+1];
525 strcpy(result_char
, result_string
.c_str());;
527 //cout << result_string.length() << endl;
528 //cout << result_char << endl;