New directory tree, with preprocessor/ inside interpretor/.
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / compiler / preprocess / preprocess.cpp
diff --git a/interpretor/preprocessor/faust-0.9.47mr3/compiler/preprocess/preprocess.cpp b/interpretor/preprocessor/faust-0.9.47mr3/compiler/preprocess/preprocess.cpp
new file mode 100644 (file)
index 0000000..f74de94
--- /dev/null
@@ -0,0 +1,540 @@
+/************************************************************************
+ ************************************************************************
+    FAUST compiler
+       Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
+    ---------------------------------------------------------------------
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ************************************************************************
+ ************************************************************************/
+
+#include "preprocess.hh"
+
+
+
+
+/****************************************************************
+                                               Parser variables
+*****************************************************************/
+
+
+int yyparse();
+
+int                    yyerr;
+extern int         yydebug;
+extern FILE*   yyin;
+Tree                   gResult;
+Tree                   gResult2;
+
+SourceReader   gReader;
+
+map<Tree, set<Tree> > gMetaDataSet;
+extern vector<Tree> gDocVector;
+extern string gDocLang;
+
+
+/****************************************************************
+                               Command line tools and arguments
+*****************************************************************/
+
+//-- globals
+string          gFaustSuperSuperDirectory;
+string          gFaustSuperDirectory;
+string          gFaustDirectory;
+string          gMasterDocument;
+string          gMasterDirectory;
+string          gMasterName;
+string          gDocName;
+Tree                   gExpandedDefList;
+
+//-- command line arguments
+
+bool                   gHelpSwitch     = false;
+bool                   gVersionSwitch  = false;
+bool            gDetailsSwitch  = false;
+bool            gDrawSignals    = false;
+bool            gShadowBlur     = false;       // note: svg2pdf doesn't like the blur filter
+bool            gGraphSwitch   = false;
+bool            gDrawPSSwitch  = false;
+bool            gDrawSVGSwitch         = false;
+bool            gPrintXMLSwitch = false;
+bool            gPrintDocSwitch = false;
+bool            gLatexDocSwitch = true;                // Only LaTeX outformat is handled for the moment.
+bool                   gStripDocSwitch = false;        // Strip <mdoc> content from doc listings.
+int                    gBalancedSwitch = 0;
+int                    gFoldThreshold  = 25;
+int                    gMaxNameSize    = 40;
+bool                   gSimpleNames    = false;
+bool            gSimplifyDiagrams = false;
+bool                   gLessTempSwitch = false;
+int                            gMaxCopyDelay   = 16;
+string                 gArchFile;
+string                 gOutputFile;
+list<string>   gInputFiles;
+
+bool            gPatternEvalMode = false;
+
+bool            gVectorSwitch   = false;
+bool            gDeepFirstSwitch= false;
+int             gVecSize        = 32;
+int             gVectorLoopVariant = 0;
+
+bool            gOpenMPSwitch   = false;
+bool            gOpenMPLoop     = false;
+bool            gSchedulerSwitch   = false;
+bool                   gGroupTaskSwitch= false;
+
+bool            gUIMacroSwitch  = false;
+bool            gDumpNorm       = false;
+
+int             gTimeout        = 120;            // time out to abort compiler (in seconds)
+
+int             gFloatSize = 1;
+
+bool                   gPrintFileListSwitch = false;
+
+string                 gClassName              = "mydsp";
+
+//-- command line tools
+
+static bool isCmd(const char* cmd, const char* kw1)
+{
+       return  (strcmp(cmd, kw1) == 0);
+}
+
+static bool isCmd(const char* cmd, const char* kw1, const char* kw2)
+{
+       return  (strcmp(cmd, kw1) == 0) || (strcmp(cmd, kw2) == 0);
+}
+
+bool process_cmdline(int argc, char* argv[])
+{
+       int     i=1; int err=0;
+
+       while (i<argc) {
+
+               if        (isCmd(argv[i], "-h", "--help")) {
+                       gHelpSwitch = true;
+                       i += 1;
+
+               } else if (isCmd(argv[i], "-v", "--version")) {
+                       gVersionSwitch = true;
+                       i += 1;
+
+               } else if (isCmd(argv[i], "-d", "--details")) {
+                       gDetailsSwitch = true;
+                       i += 1;
+
+               } else if (isCmd(argv[i], "-a", "--architecture")) {
+                       gArchFile = argv[i+1];
+                       i += 2;
+
+               } else if (isCmd(argv[i], "-o")) {
+                       gOutputFile = argv[i+1];
+                       i += 2;
+
+               } else if (isCmd(argv[i], "-ps", "--postscript")) {
+                       gDrawPSSwitch = true;
+                       i += 1;
+
+        } else if (isCmd(argv[i], "-xml", "--xml")) {
+            gPrintXMLSwitch = true;
+            i += 1;
+
+        } else if (isCmd(argv[i], "-tg", "--task-graph")) {
+            gGraphSwitch = true;
+            i += 1;
+
+        } else if (isCmd(argv[i], "-sg", "--signal-graph")) {
+            gDrawSignals = true;
+            i += 1;
+
+        } else if (isCmd(argv[i], "-blur", "--shadow-blur")) {
+            gShadowBlur = true;
+            i += 1;
+
+               } else if (isCmd(argv[i], "-svg", "--svg")) {
+                       gDrawSVGSwitch = true;
+                       i += 1;
+
+               } else if (isCmd(argv[i], "-f", "--fold")) {
+                       gFoldThreshold = atoi(argv[i+1]);
+                       i += 2;
+
+               } else if (isCmd(argv[i], "-mns", "--max-name-size")) {
+                       gMaxNameSize = atoi(argv[i+1]);
+                       i += 2;
+
+               } else if (isCmd(argv[i], "-sn", "--simple-names")) {
+                       gSimpleNames = true;
+                       i += 1;
+
+               } else if (isCmd(argv[i], "-lb", "--left-balanced")) {
+                       gBalancedSwitch = 0;
+                       i += 1;
+
+               } else if (isCmd(argv[i], "-mb", "--mid-balanced")) {
+                       gBalancedSwitch = 1;
+                       i += 1;
+
+               } else if (isCmd(argv[i], "-rb", "--right-balanced")) {
+                       gBalancedSwitch = 2;
+                       i += 1;
+
+               } else if (isCmd(argv[i], "-lt", "--less-temporaries")) {
+                       gLessTempSwitch = true;
+                       i += 1;
+
+               } else if (isCmd(argv[i], "-mcd", "--max-copy-delay")) {
+                       gMaxCopyDelay = atoi(argv[i+1]);
+                       i += 2;
+
+               } else if (isCmd(argv[i], "-sd", "--simplify-diagrams")) {
+                       gSimplifyDiagrams = true;
+                       i += 1;
+
+        } else if (isCmd(argv[i], "-vec", "--vectorize")) {
+            gVectorSwitch = true;
+            i += 1;
+
+        } else if (isCmd(argv[i], "-dfs", "--deepFirstScheduling")) {
+            gDeepFirstSwitch = true;
+            i += 1;
+
+        } else if (isCmd(argv[i], "-vs", "--vec-size")) {
+            gVecSize = atoi(argv[i+1]);
+            i += 2;
+
+        } else if (isCmd(argv[i], "-lv", "--loop-variant")) {
+            gVectorLoopVariant = atoi(argv[i+1]);
+            i += 2;
+
+        } else if (isCmd(argv[i], "-omp", "--openMP")) {
+            gOpenMPSwitch = true;
+            i += 1;
+
+        } else if (isCmd(argv[i], "-pl", "--par-loop")) {
+            gOpenMPLoop = true;
+            i += 1;
+
+        } else if (isCmd(argv[i], "-sch", "--scheduler")) {
+                       gSchedulerSwitch = true;
+                       i += 1;
+
+        } else if (isCmd(argv[i], "-g", "--groupTasks")) {
+                       gGroupTaskSwitch = true;
+                       i += 1;
+
+        } else if (isCmd(argv[i], "-uim", "--user-interface-macros")) {
+                       gUIMacroSwitch = true;
+                       i += 1;
+
+        } else if (isCmd(argv[i], "-t", "--timeout")) {
+            gTimeout = atoi(argv[i+1]);
+            i += 2;
+
+        // double float options
+        } else if (isCmd(argv[i], "-single", "--single-precision-floats")) {
+            gFloatSize = 1;
+            i += 1;
+
+        } else if (isCmd(argv[i], "-double", "--double-precision-floats")) {
+            gFloatSize = 2;
+            i += 1;
+
+        } else if (isCmd(argv[i], "-quad", "--quad-precision-floats")) {
+            gFloatSize = 3;
+            i += 1;
+                       
+        } else if (isCmd(argv[i], "-mdoc", "--mathdoc")) {
+            gPrintDocSwitch = true;
+            i += 1;
+                       
+        } else if (isCmd(argv[i], "-mdlang", "--mathdoc-lang")) {
+            gDocLang = argv[i+1];
+            i += 2;
+                       
+        } else if (isCmd(argv[i], "-stripmdoc", "--strip-mdoc-tags")) {
+            gStripDocSwitch = true;
+            i += 1;
+                       
+        } else if (isCmd(argv[i], "-flist", "--file-list")) {
+            gPrintFileListSwitch = true;
+            i += 1;
+
+        } else if (isCmd(argv[i], "-norm", "--normalized-form")) {
+            gDumpNorm = true;
+            i += 1;
+
+               } else if (isCmd(argv[i], "-cn", "--class-name")) {
+                       gClassName = argv[i+1];
+                       i += 2;
+
+        } else if (argv[i][0] != '-') {
+                       if (check_file(argv[i])) {
+                               gInputFiles.push_back(argv[i]);
+                       }
+                       i++;
+
+               } else {
+                       cerr << "faust: unrecognized option \"" << argv[i] <<"\"" << endl;
+                       i++;
+                       err++;
+               }
+       }
+
+    // adjust related options
+    if (gOpenMPSwitch || gSchedulerSwitch) gVectorSwitch = true;
+
+       return err == 0;
+}
+
+
+
+/****************************************************************
+                                        Help and Version information
+*****************************************************************/
+
+
+
+void printversion()
+{
+       cout << "FAUST, DSP to C++ compiler, Version " << FAUSTVERSION << "\n";
+       cout << "Copyright (C) 2002-2012, GRAME - Centre National de Creation Musicale. All rights reserved. \n\n";
+}
+
+
+void printhelp()
+{
+       printversion();
+       cout << "usage: faust [options] file1 [file2 ...]\n";
+       cout << "\twhere options represent zero or more compiler options \n\tand fileN represents a faust source file (.dsp extension).\n";
+
+       cout << "\noptions :\n";
+       cout << "---------\n";
+
+       cout << "-h \t\tprint this --help message\n";
+       cout << "-v \t\tprint compiler --version information\n";
+       cout << "-d \t\tprint compilation --details\n";
+    cout << "-tg \t\tprint the internal --task-graph in dot format file\n";
+    cout << "-sg \t\tprint the internal --signal-graph in dot format file\n";
+    cout << "-ps \t\tprint block-diagram --postscript file\n";
+    cout << "-svg \tprint block-diagram --svg file\n";
+    cout << "-mdoc \tprint --mathdoc of a Faust program in LaTeX format in a -mdoc directory\n";
+    cout << "-mdlang <l>\t\tload --mathdoc-lang <l> if translation file exists (<l> = en, fr, ...)\n";
+    cout << "-stripdoc \t\tapply --strip-mdoc-tags when printing Faust -mdoc listings\n";
+    cout << "-sd \t\ttry to further --simplify-diagrams before drawing them\n";
+       cout << "-f <n> \t\t--fold <n> threshold during block-diagram generation (default 25 elements) \n";
+       cout << "-mns <n> \t--max-name-size <n> threshold during block-diagram generation (default 40 char)\n";
+       cout << "-sn \t\tuse --simple-names (without arguments) during block-diagram generation\n";
+       cout << "-xml \t\tgenerate an --xml description file\n";
+    cout << "-blur \t\tadd a --shadow-blur to SVG boxes\n";
+       cout << "-lb \t\tgenerate --left-balanced expressions\n";
+       cout << "-mb \t\tgenerate --mid-balanced expressions (default)\n";
+       cout << "-rb \t\tgenerate --right-balanced expressions\n";
+       cout << "-lt \t\tgenerate --less-temporaries in compiling delays\n";
+       cout << "-mcd <n> \t--max-copy-delay <n> threshold between copy and ring buffer implementation (default 16 samples)\n";
+       cout << "-a <file> \tC++ architecture file\n";
+       cout << "-cn <name> \t--class-name <name> specify the name of the dsp class to be used instead of mydsp \n";
+       cout << "-t <sec> \t--timeout <sec>, abort compilation after <sec> seconds (default 120)\n";
+    cout << "-o <file> \tC++ output file\n";
+    cout << "-vec    \t--vectorize generate easier to vectorize code\n";
+    cout << "-vs <n> \t--vec-size <n> size of the vector (default 32 samples)\n";
+    cout << "-lv <n> \t--loop-variant [0:fastest (default), 1:simple] \n";
+    cout << "-omp    \t--openMP generate OpenMP pragmas, activates --vectorize option\n";
+    cout << "-pl     \t--par-loop generate parallel loops in --openMP mode\n";
+    cout << "-sch    \t--scheduler generate tasks and use a Work Stealing scheduler, activates --vectorize option\n";
+       cout << "-dfs    \t--deepFirstScheduling schedule vector loops in deep first order\n";
+    cout << "-g    \t\t--groupTasks group single-threaded sequential tasks together when -omp or -sch is used\n";
+    cout << "-uim    \t--user-interface-macros add user interface macro definitions in the C++ code\n";
+    cout << "-single \tuse --single-precision-floats for internal computations (default)\n";
+    cout << "-double \tuse --double-precision-floats for internal computations\n";
+    cout << "-quad \t\tuse --quad-precision-floats for internal computations\n";
+    cout << "-flist \t\tuse --file-list used to eval process\n";
+    cout << "-norm \t\t--normalized-form prints signals in normalized form and exits\n";
+
+       cout << "\nexample :\n";
+       cout << "---------\n";
+
+       cout << "faust -a jack-gtk.cpp -o myfx.cpp myfx.dsp\n";
+}
+
+
+void printheader(ostream& dst)
+{
+    // defines the metadata we want to print as comments at the begin of in the C++ file
+    set<Tree> selectedKeys;
+    selectedKeys.insert(tree("name"));
+    selectedKeys.insert(tree("author"));
+    selectedKeys.insert(tree("copyright"));
+    selectedKeys.insert(tree("license"));
+    selectedKeys.insert(tree("version"));
+
+    dst << "//-----------------------------------------------------" << endl;
+    for (map<Tree, set<Tree> >::iterator i = gMetaDataSet.begin(); i != gMetaDataSet.end(); i++) {
+        if (selectedKeys.count(i->first)) {
+            dst << "// " << *(i->first);
+            const char* sep = ": ";
+            for (set<Tree>::iterator j = i->second.begin(); j != i->second.end(); ++j) {
+                dst << sep << **j;
+                sep = ", ";
+            }
+            dst << endl;
+        }
+    }
+
+    dst << "//" << endl;
+    dst << "// Code generated with Faust " << FAUSTVERSION << " (http://faust.grame.fr)" << endl;
+    dst << "//-----------------------------------------------------" << endl;
+}
+
+
+
+
+/****************************************************************
+                                                               MAIN
+*****************************************************************/
+
+
+
+/**
+ * transform a filename "faust/example/noise.dsp" into
+ * the corresponding fx name "noise"
+ */
+static string fxname(const string& filename)
+{
+       // determine position right after the last '/' or 0
+       unsigned int p1 = 0;
+    for (unsigned int i=0; i<filename.size(); i++) {
+        if (filename[i] == '/')  { p1 = i+1; }
+    }
+       
+       // determine position of the last '.'
+       unsigned int p2 = filename.size();
+    for (unsigned int i=p1; i<filename.size(); i++) {
+        if (filename[i] == '.')  { p2 = i; }
+    }
+
+    return filename.substr(p1, p2-p1);
+}
+
+
+static void initFaustDirectories()
+{
+    char s[1024];
+    getFaustPathname(s, 1024);
+
+    gFaustDirectory = filedirname(s);
+    gFaustSuperDirectory = filedirname(gFaustDirectory);
+    gFaustSuperSuperDirectory = filedirname(gFaustSuperDirectory);
+    if (gInputFiles.empty()) {
+        gMasterDocument = "Unknown";
+        gMasterDirectory = ".";
+               gMasterName = "faustfx";
+               gDocName = "faustdoc";
+    } else {
+        gMasterDocument = *gInputFiles.begin();
+        gMasterDirectory = filedirname(gMasterDocument);
+               gMasterName = fxname(gMasterDocument);
+               gDocName = fxname(gMasterDocument);
+    }
+}
+
+char* preProcess (char* file_route)
+{
+  
+       /****************************************************************
+        1 - process command line
+       *****************************************************************/
+        int argc = 3;
+       char* argv[3];
+       argv[0] = "faust";
+       argv[1] = "-d";
+       argv[2] = file_route;
+
+       process_cmdline(argc, argv);
+
+       if (gHelpSwitch)                { printhelp(); exit(0); }
+       if (gVersionSwitch)     { printversion(); exit(0); }
+
+    initFaustDirectories();
+#ifndef WIN32
+    alarm(gTimeout);
+#endif
+
+
+       /****************************************************************
+        2 - parse source files
+       *****************************************************************/
+
+       startTiming("parser");
+
+       
+       list<string>::iterator s;
+       gResult2 = nil;
+       yyerr = 0;
+
+       if (gInputFiles.begin() == gInputFiles.end()) {
+               cerr << "ERROR: no files specified;" << endl;
+               cerr << "interpreter <program.dsp> [input.wav]." << endl;
+               exit(1);
+       }
+       for (s = gInputFiles.begin(); s != gInputFiles.end(); s++) {
+               if (s == gInputFiles.begin()) gMasterDocument = *s;
+               gResult2 = cons(importFile(tree(s->c_str())), gResult2);
+       }
+       if (yyerr > 0) {
+               //fprintf(stderr, "Erreur de parsing 2, count = %d \n", yyerr);
+               exit(1);
+       }
+       gExpandedDefList = gReader.expandlist(gResult2);
+
+       endTiming("parser");
+       
+       /****************************************************************
+        3 - evaluate 'process' definition
+       *****************************************************************/
+       
+       startTiming("evaluation");
+
+       Tree process = evalprocess(gExpandedDefList);
+
+       if (gErrorCount > 0) {
+       // cerr << "Total of " << gErrorCount << " errors during evaluation of : process = " << boxpp(process) << ";\n";
+        cerr << "Total of " << gErrorCount << " errors during the compilation of  " << gMasterDocument << ";\n";
+               exit(1);
+       }
+
+       endTiming("evaluation");
+
+       ostringstream result_stream;
+       result_stream << boxpp(process);
+       string result_string = result_stream.str();
+       char* result_char = new char [result_string.length()+1];
+       strcpy(result_char, result_string.c_str());;
+
+       //cout << result_string.length() << endl;
+       //cout << result_char << endl;
+
+       // Karim Barkati: printing globals value
+       //list<string> faustGlobals = {
+       //cout << "gFaustSuperSuperDirectory = " << gFaustSuperSuperDirectory << endl;
+       //cout << "gFaustSuperDirectory = " << gFaustSuperDirectory << endl;
+       //cout << "gFaustDirectory = " << gFaustDirectory << endl;
+       //cout << "gMasterDocument = " << gMasterDocument << endl;
+       //cout << "gMasterDirectory = " << gMasterDirectory << endl;
+       //cout << "gMasterName = " << gMasterName << endl;
+
+       return result_char;
+}