00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #define FAUSTVERSION "0.9.9.4"
00022
00023 #include <stdio.h>
00024 #include <string.h>
00025
00026 #include <assert.h>
00027
00028 #include "signals.hh"
00029 #include "sigtype.hh"
00030 #include "sigtyperules.hh"
00031 #include "sigprint.hh"
00032 #include "simplify.hh"
00033 #include "privatise.hh"
00034
00035 #include "compile_scal.hh"
00036 #include "compile_vect.hh"
00037 #include "propagate.hh"
00038 #include "errormsg.hh"
00039 #include "ppbox.hh"
00040 #include "enrobage.hh"
00041 #include "eval.hh"
00042 #include "description.hh"
00043
00044 #include <map>
00045 #include <string>
00046 #include <vector>
00047 #include <iostream>
00048 #include <fstream>
00049 #include <sstream>
00050
00051 #include "sourcereader.hh"
00052
00053
00054
00055
00056 #include "schema.h"
00057 #include "drawschema.hh"
00058
00059
00060 using namespace std ;
00061
00062
00063
00064
00065
00066
00067
00068 int yyparse();
00069
00070 int yyerr;
00071 extern int yydebug;
00072 extern FILE* yyin;
00073 Tree gResult;
00074 Tree gResult2;
00075
00076 SourceReader gReader;
00077
00078 map<Tree, set<Tree> > gMetaDataSet;
00079
00080
00081
00082
00083
00084
00085
00086
00087 bool gHelpSwitch = false;
00088 bool gVersionSwitch = false;
00089 bool gDetailsSwitch = false;
00090 bool gVectorSwitch = false;
00091 bool gDrawPSSwitch = false;
00092 bool gDrawSVGSwitch = false;
00093 bool gPrintXMLSwitch = false;
00094 int gBalancedSwitch = 0;
00095 int gFoldThreshold = 25;
00096 int gMaxNameSize = 40;
00097 bool gSimpleNames = false;
00098 bool gLessTempSwitch = false;
00099 int gMaxCopyDelay = 16;
00100
00101 string gArchFile;
00102 string gOutputFile;
00103 list<string> gInputFiles;
00104
00105 bool gPatternEvalMode = false;
00106
00107
00108
00109 static bool isCmd(const char* cmd, const char* kw1)
00110 {
00111 return (strcmp(cmd, kw1) == 0);
00112 }
00113
00114 static bool isCmd(const char* cmd, const char* kw1, const char* kw2)
00115 {
00116 return (strcmp(cmd, kw1) == 0) || (strcmp(cmd, kw2) == 0);
00117 }
00118
00119 bool process_cmdline(int argc, char* argv[])
00120 {
00121 int i=1; int err=0;
00122
00123 while (i<argc) {
00124
00125 if (isCmd(argv[i], "-h", "--help")) {
00126 gHelpSwitch = true;
00127 i += 1;
00128
00129 } else if (isCmd(argv[i], "-v", "--version")) {
00130 gVersionSwitch = true;
00131 i += 1;
00132
00133 } else if (isCmd(argv[i], "-d", "--details")) {
00134 gDetailsSwitch = true;
00135 i += 1;
00136
00137 } else if (isCmd(argv[i], "-a", "--architecture")) {
00138 gArchFile = argv[i+1];
00139 i += 2;
00140
00141 } else if (isCmd(argv[i], "-o")) {
00142 gOutputFile = argv[i+1];
00143 i += 2;
00144
00145 } else if (isCmd(argv[i], "-vec", "--vectorize")) {
00146 gVectorSwitch = true;
00147 i += 1;
00148
00149 } else if (isCmd(argv[i], "-ps", "--postscript")) {
00150 gDrawPSSwitch = true;
00151 i += 1;
00152
00153 } else if (isCmd(argv[i], "-xml", "--xml")) {
00154 gPrintXMLSwitch = true;
00155 i += 1;
00156
00157 } else if (isCmd(argv[i], "-svg", "--svg")) {
00158 gDrawSVGSwitch = true;
00159 i += 1;
00160
00161 } else if (isCmd(argv[i], "-f", "--fold")) {
00162 gFoldThreshold = atoi(argv[i+1]);
00163 i += 2;
00164
00165 } else if (isCmd(argv[i], "-mns", "--max-name-size")) {
00166 gMaxNameSize = atoi(argv[i+1]);
00167 i += 2;
00168
00169 } else if (isCmd(argv[i], "-sn", "--simple-names")) {
00170 gSimpleNames = true;
00171 i += 1;
00172
00173 } else if (isCmd(argv[i], "-lb", "--left-balanced")) {
00174 gBalancedSwitch = 0;
00175 i += 1;
00176
00177 } else if (isCmd(argv[i], "-mb", "--mid-balanced")) {
00178 gBalancedSwitch = 1;
00179 i += 1;
00180
00181 } else if (isCmd(argv[i], "-rb", "--right-balanced")) {
00182 gBalancedSwitch = 2;
00183 i += 1;
00184
00185 } else if (isCmd(argv[i], "-lt", "--less-temporaries")) {
00186 gLessTempSwitch = true;
00187 i += 1;
00188
00189 } else if (isCmd(argv[i], "-mcd", "--max-copy-delay")) {
00190 gMaxCopyDelay = atoi(argv[i+1]);
00191 i += 2;
00192
00193 } else if (argv[i][0] != '-') {
00194 if (check_file(argv[i])) {
00195 gInputFiles.push_back(argv[i]);
00196 }
00197 i++;
00198
00199 } else {
00200 cerr << "faust: unrecognized option \"" << argv[i] <<"\"" << endl;
00201 i++;
00202 err++;
00203 }
00204 }
00205
00206 return err == 0;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 void printversion()
00218 {
00219 cout << "FAUST, DSP to C++ compiler, Version " << FAUSTVERSION << "\n";
00220 cout << "Copyright (C) 2002-2008, GRAME - Centre National de Creation Musicale. All rights reserved. \n\n";
00221 }
00222
00223
00224 void printhelp()
00225 {
00226 printversion();
00227 cout << "usage: faust [options] file1 [file2 ...]\n";
00228 cout << "\twhere options represent zero or more compiler options \n\tand fileN represents a faust source file (.dsp extension).\n";
00229
00230 cout << "\noptions :\n";
00231 cout << "---------\n";
00232
00233 cout << "-h \t\tprint this --help message\n";
00234 cout << "-v \t\tprint compiler --version information\n";
00235 cout << "-d \t\tprint compilation --details\n";
00236 cout << "-ps \t\tprint block-diagram --postscript file\n";
00237 cout << "-svg \t\tprint block-diagram --svg file\n";
00238 cout << "-f <n> \t\t--fold <n> threshold during block-diagram generation (default 25 elements) \n";
00239 cout << "-mns <n> \t--max-name-size <n> threshold during block-diagram generation (default 40 char)\n";
00240 cout << "-sn \t\tuse --simple-names (without arguments) during block-diagram generation\n";
00241 cout << "-xml \t\tgenerate an --xml description file\n";
00242 cout << "-lb \t\tgenerate --left-balanced expressions\n";
00243 cout << "-mb \t\tgenerate --mid-balanced expressions (default)\n";
00244 cout << "-rb \t\tgenerate --right-balanced expressions\n";
00245 cout << "-lt \t\tgenerate --less-temporaries in compiling delays\n";
00246 cout << "-mcd <n> \t--max-copy-delay <n> threshold between copy and ring buffer implementation (default 16 samples)\n";
00247 cout << "-a <file> \tC++ wrapper file\n";
00248 cout << "-o <file> \tC++ output file\n";
00249
00250
00251 cout << "\nexample :\n";
00252 cout << "---------\n";
00253
00254 cout << "faust -a jack-gtk.cpp -o myfx.cpp myfx.dsp\n";
00255 }
00256
00257
00258 void printheader(ostream& dst)
00259 {
00260 Tree author = tree("author");
00261
00262 dst << "//-----------------------------------------------------" << endl;
00263 for (map<Tree, set<Tree> >::iterator i = gMetaDataSet.begin(); i != gMetaDataSet.end(); i++) {
00264 dst << "// " << *(i->first) << " : ";
00265 if (i->first != author) {
00266 dst << **(i->second.begin());
00267 } else {
00268 for (set<Tree>::iterator j = i->second.begin(); j != i->second.end(); j++) {
00269 if (j != i->second.begin()) { dst << endl << "// contributors : "; }
00270 dst << **j << " ";
00271 }
00272 }
00273 dst << endl;
00274 }
00275
00276 dst << "//" << endl;
00277 dst << "// Code generated with Faust " << FAUSTVERSION << " (http://faust.grame.fr)" << endl;
00278 dst << "//-----------------------------------------------------" << endl;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 int main (int argc, char* argv[])
00291 {
00292
00293
00294
00295
00296
00297 process_cmdline(argc, argv);
00298
00299 if (gHelpSwitch) { printhelp(); exit(0); }
00300 if (gVersionSwitch) { printversion(); exit(0); }
00301
00302
00303
00304
00305
00306
00307 list<string>::iterator s;
00308 gResult2 = nil;
00309 yyerr = 0;
00310 string masterFilename = "unknow";
00311
00312 if (gInputFiles.begin() == gInputFiles.end()) {
00313 cerr << "ERROR: no files specified; for help type \"faust --help\"" << endl;
00314 exit(1);
00315 }
00316 for (s = gInputFiles.begin(); s != gInputFiles.end(); s++) {
00317 if (s == gInputFiles.begin()) masterFilename = *s;
00318 gResult2 = cons(importFile(tree(s->c_str())), gResult2);
00319 }
00320 if (yyerr > 0) {
00321
00322 exit(1);
00323 }
00324
00325
00326
00327
00328
00329
00330 Tree process = evalprocess(gReader.expandlist(gResult2));
00331 if (gErrorCount > 0) {
00332
00333 cerr << "Total of " << gErrorCount << " errors during the compilation of " << masterFilename << ";\n";
00334 exit(1);
00335 }
00336
00337
00338 if (gDetailsSwitch) { cerr << "process = " << boxpp(process) << ";\n"; }
00339
00340 if (gDrawPSSwitch) { drawSchema( process, subst("$0-ps", masterFilename).c_str(), "ps" ); }
00341 if (gDrawSVGSwitch) { drawSchema( process, subst("$0-svg", masterFilename).c_str(), "svg" ); }
00342
00343
00344 int numInputs, numOutputs;
00345 if (!getBoxType(process, &numInputs, &numOutputs)) {
00346 cerr << "ERROR during the evaluation of process : "
00347 << boxpp(process) << endl;
00348 exit(1);
00349 }
00350
00351 if (gDetailsSwitch) { cerr <<"process has " <<numInputs <<" inputs, and " <<numOutputs <<" outputs" <<endl; }
00352
00353
00354
00355
00356
00357
00358 Tree lsignals = boxPropagateSig(nil, process , makeSigInputList(numInputs) );
00359 if (gDetailsSwitch) { cerr << "output signals are : " << endl; printSignal(lsignals, stderr); }
00360
00361
00362
00363
00364
00365
00366 Compiler* C;
00367 if (gVectorSwitch) C = new VectorCompiler("mydsp", "dsp", numInputs, numOutputs);
00368 else C = new ScalarCompiler("mydsp", "dsp", numInputs, numOutputs);
00369
00370 if (gPrintXMLSwitch) C->setDescription(new Description());
00371
00372 C->compileMultiSignal(lsignals);
00373
00374
00375
00376
00377
00378
00379 if (gPrintXMLSwitch) {
00380 Description* D = C->getDescription(); assert(D);
00381 ostream* xout = new ofstream(subst("$0.xml", masterFilename).c_str());
00382
00383 if(gMetaDataSet.count(tree("name"))>0) D->name(tree2str(*(gMetaDataSet[tree("name")].begin())));
00384 if(gMetaDataSet.count(tree("author"))>0) D->author(tree2str(*(gMetaDataSet[tree("author")].begin())));
00385 if(gMetaDataSet.count(tree("copyright"))>0) D->copyright(tree2str(*(gMetaDataSet[tree("copyright")].begin())));
00386 if(gMetaDataSet.count(tree("license"))>0) D->license(tree2str(*(gMetaDataSet[tree("license")].begin())));
00387 if(gMetaDataSet.count(tree("version"))>0) D->version(tree2str(*(gMetaDataSet[tree("version")].begin())));
00388
00389 D->inputs(C->getClass()->inputs());
00390 D->outputs(C->getClass()->outputs());
00391
00392 D->print(0, *xout);
00393 }
00394
00395
00396
00397
00398
00399
00400 ostream* dst;
00401 istream* enrobage;
00402 istream* intrinsic;
00403
00404 if (gOutputFile != "") {
00405 dst = new ofstream(gOutputFile.c_str());
00406 } else {
00407 dst = &cout;
00408 }
00409
00410
00411 if (gArchFile != "") {
00412 if ( (enrobage = open_arch_stream(gArchFile.c_str())) ) {
00413 printheader(*dst);
00414 C->getClass()->printLibrary(*dst);
00415 C->getClass()->printIncludeFile(*dst);
00416
00417 streamCopyUntil(*enrobage, *dst, "<<includeIntrinsic>>");
00418 if ( gVectorSwitch && (intrinsic = open_arch_stream("intrinsic.hh")) ) {
00419 streamCopyUntilEnd(*intrinsic, *dst);
00420 }
00421
00422 streamCopyUntil(*enrobage, *dst, "<<includeclass>>");
00423 C->getClass()->println(0,*dst);
00424 streamCopyUntilEnd(*enrobage, *dst);
00425 } else {
00426 cerr << "ERROR : can't open architecture file " << gArchFile << endl;
00427 return 1;
00428 }
00429 } else {
00430 printheader(*dst);
00431 C->getClass()->printLibrary(*dst);
00432 C->getClass()->printIncludeFile(*dst);
00433 C->getClass()->println(0,*dst);
00434 }
00435
00436 return 0;
00437 }