00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00043 #include <stdio.h>
00044 #include <string.h>
00045 #include <errno.h>
00046 #include <sys/stat.h>
00047 #include <time.h>
00048 #include <algorithm>
00049 #include <functional>
00050
00051 #include <iostream>
00052 #include <fstream>
00053 #include <sstream>
00054
00055 #include <map>
00056 #include <string>
00057 #include <vector>
00058
00059 #include "ppbox.hh"
00060 #include "prim2.hh"
00061 #include "doc.hh"
00062 #include "eval.hh"
00063 #include "errormsg.hh"
00064 #include "doc_Text.hh"
00065 #include "sigprint.hh"
00066 #include "propagate.hh"
00067 #include "enrobage.hh"
00068 #include "drawschema.hh"
00069 #include "names.hh"
00070 #include "simplify.hh"
00071 #include "privatise.hh"
00072 #include "recursivness.hh"
00073 #include "sourcereader.hh"
00074 #include "lateq.hh"
00075 #include "doc_compile.hh"
00076 #include "doc_lang.hh"
00077 #include "doc_notice.hh"
00078 #include "doc_autodoc.hh"
00079 #include "compatibility.hh"
00080
00081
00082
00083 #define MAXIDCHARS 5
00084
00085 using namespace std ;
00086
00087
00088
00089
00090
00091
00092 extern Tree gExpandedDefList;
00093 extern map<Tree, set<Tree> > gMetaDataSet;
00094 extern map<string, string> gDocMetadatasStringMap;
00095 extern bool gDetailsSwitch;
00096 extern bool gStripDocSwitch;
00097 extern string gFaustDirectory;
00098 extern string gFaustSuperDirectory;
00099 extern string gFaustSuperSuperDirectory;
00100 extern string gMasterDocument;
00101 extern SourceReader gReader;
00102
00103 extern string gDocName;
00104 static const char* gDocDevSuffix;
00105 static string gCurrentDir;
00106 static const string gLatexheaderfilename = "latexheader.tex";
00107
00108 vector<Tree> gDocVector;
00109
00110 static struct tm gCompilationDate;
00111
00112 enum { langEN, langFR, langIT };
00113 string gDocLang;
00114
00115
00116 static void printdocheader(ostream& docout);
00117 static void printlatexheader(istream& latexheader, ostream& docout);
00118 static void printfaustlistings(ostream& docout);
00119 static void printfaustlisting(string& path, ostream& docout);
00120 static void printlatexfooter(ostream& docout);
00121 static void printdoccontent(const char* svgTopDir, const vector<Tree>& docVector, const string& faustversion, ostream& docout);
00122 static void printfaustdocstamp(const string& faustversion, ostream& docout);
00123 static void printDocEqn(Lateq* ltq, ostream& docout);
00124 static void printDocDgm(const Tree expr, const char* svgTopDir, ostream& docout, int i);
00125
00126
00127 static void prepareDocEqns( const vector<Tree>& docBoxes, vector<Lateq*>& docCompiledEqnsVector );
00128 static void collectDocEqns( const vector<Tree>& docBoxes, vector<Tree>& eqBoxes );
00129 static void mapEvalDocEqn( const vector<Tree>& eqBoxes, const Tree& env, vector<Tree>& evalEqBoxes );
00130 static void mapGetEqName( const vector<Tree>& evalEqBoxes, vector<string>& eqNames );
00131 static void calcEqnsNicknames( const vector<string>& eqNames, vector<string>& eqNicknames );
00132 static void mapPrepareEqSig( const vector<Tree>& evalEqBoxes, vector<int>& eqInputs, vector<int>& eqOutputs, vector<Tree>& eqSigs );
00133 static void mapSetSigNickname( const vector<string>& eqNicknames, const vector<int>& eqInputs, const vector<Tree>& eqSigs );
00134 static void collectEqSigs( const vector<Tree>& eqSigs, Tree& superEqList );
00135 static void annotateSuperList( DocCompiler* DC, Tree superEqList );
00136
00137 static void mapCompileDocEqnSigs( const vector<Tree>& eqSigs, const vector<int>& eqInputs, const vector<int>& eqOutputs, DocCompiler* DC, vector<Lateq*>& docCompiledEqnsVector );
00138
00139
00140 static string calcNumberedName(const char* base, int i);
00141 static void getBoxInputsAndOutputs(const Tree t, int& numInputs, int& numOutputs);
00142 static string calcDocEqnInitial(const string s);
00143
00144
00145 static void initCompilationDate();
00146 static struct tm* getCompilationDate();
00147
00148
00149 static int cholddir ();
00150 static int mkchdir(const char* dirname);
00151 static int makedir(const char* dirname);
00152 static void getCurrentDir();
00153 static istream* openArchFile (const string& filename);
00154 static char* legalFileName(const Tree t, int n, char* dst);
00155 static string rmExternalDoubleQuotes(const string& s);
00156 static void copyFaustSources(const char* projname, const vector<string>& pathnames);
00157
00158
00159
00160
00161
00162
00163
00164
00165 Sym DOCTXT = symbol ("DocTxt");
00166 Tree docTxt(const char* name) { return tree( DOCTXT, tree(symbol(name)) ); }
00167 bool isDocTxt(Tree t) { return t->node() == Node(DOCTXT); }
00168 bool isDocTxt(Tree t0, const char** str)
00169 {
00170 Tree t1; Sym s;
00171 if ( isTree(t0, DOCTXT, t1) && isSym(t1->node(), &s) ) {
00172 *str = name(s);
00173 return true;
00174 } else {
00175 return false;
00176 }
00177 }
00178
00179 Sym DOCEQN = symbol ("DocEqn");
00180 Tree docEqn(Tree x) { return tree(DOCEQN, x); }
00181 bool isDocEqn(Tree t, Tree& x) { return isTree(t, DOCEQN, x); }
00182
00183 Sym DOCDGM = symbol ("DocDgm");
00184 Tree docDgm(Tree x) { return tree(DOCDGM, x); }
00185 bool isDocDgm(Tree t, Tree& x) { return isTree(t, DOCDGM, x); }
00186
00187 Sym DOCNTC = symbol ("DocNtc");
00188 Tree docNtc() { return tree(DOCNTC); }
00189 bool isDocNtc(Tree t) { return isTree(t, DOCNTC); }
00190
00191 Sym DOCLST = symbol ("DocLst");
00192 Tree docLst() { return tree(DOCLST); }
00193 bool isDocLst(Tree t) { return isTree(t, DOCLST); }
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00216 void printDoc(const char* projname, const char* docdev, const char* faustversion)
00217 {
00218 gDocDevSuffix = docdev;
00219
00221
00222
00223
00224
00225
00226 makedir(projname);
00227
00228 string svgTopDir = subst("$0/svg", projname);
00229 makedir(svgTopDir.c_str());
00230
00231 string cppdir = subst("$0/cpp", projname);
00232 makedir(cppdir.c_str());
00233
00234 string pdfdir = subst("$0/pdf", projname);
00235 makedir(pdfdir.c_str());
00236
00237
00238 vector<string> pathnames = gReader.listSrcFiles();
00239 copyFaustSources(projname, pathnames);
00240
00241 string texdir = subst("$0/tex", projname);
00242 mkchdir(texdir.c_str());
00243
00245 ofstream docout(subst("$0.$1", gDocName, docdev).c_str());
00246 cholddir();
00247
00249 loadTranslationFile(gDocLang);
00250
00252 if (gDocVector.empty()) { declareAutoDoc(); }
00253
00255 printfaustdocstamp(faustversion, docout);
00256 istream* latexheader = openArchFile(gLatexheaderfilename);
00257 printlatexheader(*latexheader, docout);
00258 printdocheader(docout);
00259 printdoccontent(svgTopDir.c_str(), gDocVector, faustversion, docout);
00260 printlatexfooter(docout);
00261
00262 }
00263
00264
00265
00266
00267
00268
00269
00276 static void printlatexheader(istream& latexheader, ostream& docout)
00277 {
00278 string s;
00279 while(getline(latexheader, s)) docout << s << endl;
00280 }
00281
00287 static void printdocheader(ostream& docout)
00288 {
00289
00290 set<Tree> selectedKeys;
00291 selectedKeys.insert(tree("name"));
00292 selectedKeys.insert(tree("author"));
00293 selectedKeys.insert(tree("copyright"));
00294 selectedKeys.insert(tree("license"));
00295 selectedKeys.insert(tree("version"));
00296
00297 string title = "Documentation";
00298 if (gMetaDataSet.count(tree("name"))) {
00299 title = unquote( tree2str(*(gMetaDataSet[tree("name")].begin())) );
00300 }
00301 docout << "\\title{" << title << "}" << endl;
00302
00303 string author = "(anonymous)";
00304 if (gMetaDataSet.count(tree("author"))) {
00305 author = unquote( tree2str(*(gMetaDataSet[tree("author")].begin())) );
00306 docout << "\\author{" << author << "}" << endl;
00307 }
00308
00309 docout << "\\date{\\today}" << endl << endl;
00310 docout << "\\maketitle" << endl << endl;
00311
00312
00313 if (! gMetaDataSet.empty()) {
00314 docout << "\\begin{tabular}{ll}" << endl;
00315 docout << "\t\\hline" << endl;
00316 for (map<Tree, set<Tree> >::iterator i = gMetaDataSet.begin(); i != gMetaDataSet.end(); i++) {
00317 if (selectedKeys.count(i->first)) {
00318
00319 docout << "\t\\textbf{" << gDocMetadatasStringMap[tree2str(i->first)];
00320 const char* sep = "} & ";
00321 for (set<Tree>::iterator j = i->second.begin(); j != i->second.end(); j++) {
00322 docout << sep << rmExternalDoubleQuotes(tree2str(*j));
00323 sep = ", ";
00324 }
00325 const char* sep2 = "\\\\";
00326 docout << sep2 << endl;
00327 }
00328 }
00329 docout << "\t\\hline\\\\" << endl;
00330 docout << "\\end{tabular}" << endl;
00331 docout << "\\bigskip" << endl << endl;
00332 }
00333 }
00334
00335
00342 static void printfaustlistings(ostream& docout)
00343 {
00344 vector<string> pathnames = gReader.listSrcFiles();
00345
00346
00347 for (unsigned int i=0; i< pathnames.size(); i++) {
00348 printfaustlisting(pathnames[i], docout);
00349 }
00350 }
00351
00352
00360 static void printfaustlisting(string& faustfile, ostream& docout)
00361 {
00362 string s;
00363 ifstream src;
00364
00365
00366 src.open(faustfile.c_str(), ifstream::in);
00367
00368 docout << endl << "\\bigskip\\bigskip" << endl;
00369 docout << "\\begin{lstlisting}[caption=\\texttt{" << filebasename(faustfile.c_str()) << "}]" << endl;
00370
00371 bool isInsideDoc = false;
00372
00373 if (faustfile != "" && src.good()) {
00374 while(getline(src, s)) {
00375 size_t foundopendoc = s.find("<mdoc>");
00376 if (foundopendoc != string::npos && gStripDocSwitch) isInsideDoc = true;
00377
00378 if (isInsideDoc == false)
00379 docout << s << endl;
00380
00381 size_t foundclosedoc = s.find("</mdoc>");
00382 if (foundclosedoc != string::npos && gStripDocSwitch) isInsideDoc = false;
00383 }
00384 } else {
00385 cerr << "ERROR : can't open faust source file " << faustfile << endl;
00386 exit(1);
00387 }
00388
00389 docout << "\\end{lstlisting}" << endl << endl;
00390 }
00391
00392
00398 static void printlatexfooter(ostream& docout)
00399 {
00400 docout << endl << "\\end{document}" << endl << endl;
00401 }
00402
00403
00413 static void printfaustdocstamp(const string& faustversion, ostream& docout)
00414 {
00415 char datebuf [150];
00416 strftime (datebuf, 150, "%c", getCompilationDate());
00417
00418 docout << "%% This documentation was generated with Faust version " << faustversion << endl;
00419 docout << "%% " << datebuf << endl;
00420 docout << "%% http://faust.grame.fr" << endl << endl;
00421 }
00422
00423
00424
00425
00426
00427
00428
00445 static void printdoccontent(const char* svgTopDir, const vector<Tree>& docVector, const string& faustversion, ostream& docout)
00446 {
00447
00448
00450 vector<Lateq*> docCompiledEqnsVector;
00451 prepareDocEqns( docVector, docCompiledEqnsVector );
00452
00453 vector<Lateq*>::iterator eqn_it = docCompiledEqnsVector.begin();
00454 int i = 1;
00455
00457 for (vector<Tree>::const_iterator doc=docVector.begin(); doc<docVector.end(); doc++) {
00458
00459 Tree L = reverse(*doc);
00460
00461
00463 while (isList(L)) {
00464 Tree expr;
00465 if ( isDocEqn(hd(L), expr) ) {
00466 printDocEqn(*eqn_it++, docout);
00467 }
00468 else if ( isDocDgm(hd(L), expr) ) {
00469 printDocDgm(expr, svgTopDir, docout, i++);
00470 }
00471 else if ( isDocTxt(hd(L)) ) {
00472 docout << *hd(L)->branch(0) << endl;
00473 }
00474 else if ( isDocNtc(hd(L)) ) {
00475 printDocNotice(faustversion, docout);
00476 }
00477 else if ( isDocLst(hd(L)) ) {
00478 printfaustlistings(docout);
00479 }
00480 else {
00481 cerr << "ERROR : " << *hd(L) << " is not a valid documentation type." << endl;
00482 }
00483 L = tl(L);
00484 }
00485
00486 }
00487 }
00488
00489
00490
00491
00492
00493
00494
00505 static void prepareDocEqns(const vector<Tree>& docBoxes, vector<Lateq*>& docCompiledEqnsVector)
00506 {
00507 vector<Tree> eqBoxes; collectDocEqns( docBoxes, eqBoxes );
00508 vector<Tree> evalEqBoxes; mapEvalDocEqn( eqBoxes, gExpandedDefList, evalEqBoxes );
00509 vector<string> eqNames; mapGetEqName( evalEqBoxes, eqNames );
00510 vector<string> eqNicknames; calcEqnsNicknames( eqNames, eqNicknames );
00511
00512 vector<int> eqInputs;
00513 vector<int> eqOutputs;
00514 vector<Tree> eqSigs; mapPrepareEqSig( evalEqBoxes, eqInputs, eqOutputs, eqSigs );
00515 mapSetSigNickname( eqNicknames, eqInputs, eqSigs );
00516 Tree superEqList; collectEqSigs( eqSigs, superEqList );
00517
00518 DocCompiler* DC = new DocCompiler(0, 0);
00519 annotateSuperList( DC, superEqList );
00520
00521 mapCompileDocEqnSigs( eqSigs, eqInputs, eqOutputs, DC, docCompiledEqnsVector );
00522 }
00523
00524
00531 static void collectDocEqns(const vector<Tree>& docBoxes, vector<Tree>& eqBoxes)
00532 {
00533 int nbdoceqn = 0;
00534
00535 for (vector<Tree>::const_iterator doc=docBoxes.begin(); doc<docBoxes.end(); doc++) {
00536 Tree L = reverse(*doc);
00537 Tree expr;
00538 while (isList(L)) {
00539 if ( isDocEqn(hd(L), expr) ) {
00540 eqBoxes.push_back(expr);
00541 nbdoceqn++;
00542 }
00543 L = tl(L);
00544 }
00545 }
00546
00547 }
00548
00549
00557 static void mapEvalDocEqn(const vector<Tree>& eqBoxes, const Tree& env, vector<Tree>& evalEqBoxes)
00558 {
00559
00560
00561 for ( vector<Tree>::const_iterator eq=eqBoxes.begin(); eq < eqBoxes.end(); eq++)
00562 {
00563 evalEqBoxes.push_back(evaldocexpr( *eq, env ));
00564 }
00565
00566 }
00567
00568
00575 static void mapGetEqName(const vector<Tree>& evalEqBoxes, vector<string>& eqNames)
00576 {
00577
00578
00579 int i = 1;
00580 for( vector<Tree>::const_iterator eq = evalEqBoxes.begin(); eq < evalEqBoxes.end(); eq++, i++ ) {
00581 Tree id;
00582 string s;
00583 int n,m; getBoxType(*eq, &n, &m);
00584 if ( n==0 && getDefNameProperty(*eq, id) ) {
00585 s = tree2str(id);
00586 }
00587 else {
00588 s = calcNumberedName("doceqn-", i);
00589 }
00590 eqNames.push_back( s ) ;
00591 }
00592
00593 }
00594
00595
00605 static void calcEqnsNicknames(const vector<string>& eqNames, vector<string>& eqNicknames)
00606 {
00607
00608
00609 vector<string> v;
00610
00611 for( vector<string>::const_iterator eq = eqNames.begin(); eq < eqNames.end(); eq++ ) {
00612 string init = calcDocEqnInitial(*eq);
00613 v.push_back(init);
00615
00616
00617
00618
00619
00620 eqNicknames.push_back(init);
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 }
00635
00636
00645 static void mapPrepareEqSig(const vector<Tree>& evalEqBoxes, vector<int>& eqInputs, vector<int>& eqOutputs, vector<Tree>& eqSigs)
00646 {
00647
00648
00649 for( vector<Tree>::const_iterator eq = evalEqBoxes.begin(); eq < evalEqBoxes.end(); eq++ ) {
00650
00651 int numInputs, numOutputs;
00652 getBoxInputsAndOutputs(*eq, numInputs, numOutputs);
00653
00654 eqInputs.push_back(numInputs);
00655 eqOutputs.push_back(numOutputs);
00656
00657 Tree lsig1 = boxPropagateSig( nil, *eq , makeSigInputList(numInputs) );
00658
00659
00660 Tree lsig2 = deBruijn2Sym(lsig1);
00661 Tree lsig3 = simplify(lsig2);
00662
00663 Tree lsig4 = docTableConvertion(lsig3);
00664
00665
00666 eqSigs.push_back(lsig4);
00667 }
00668
00669 }
00670
00671
00679 static void mapSetSigNickname(const vector<string>& eqNicknames, const vector<int>& eqInputs, const vector<Tree>& eqSigs)
00680 {
00681
00682
00683
00684
00685
00686
00687
00688
00689 }
00690
00691
00698 static void collectEqSigs(const vector<Tree>& eqSigs, Tree& superEqList)
00699 {
00700
00701
00702 superEqList = nil;
00703
00704 for( vector<Tree>::const_iterator it = eqSigs.begin(); it < eqSigs.end(); ++it ) {
00705 superEqList = cons( *it, superEqList );
00706 }
00707
00708
00709
00710 }
00711
00712
00719 static void annotateSuperList(DocCompiler* DC, Tree superEqList)
00720 {
00721 DC->annotate(superEqList);
00722 }
00723
00724
00726
00727
00728
00729
00730
00731
00732
00733
00734
00742 static void mapCompileDocEqnSigs(const vector<Tree>& eqSigs, const vector<int>& eqInputs, const vector<int>& eqOutputs, DocCompiler* DC, vector<Lateq*>& docCompiledEqnsVector)
00743 {
00744
00745
00746 for( unsigned int i=0; i < eqSigs.size(); i++ ) {
00747
00748
00749 docCompiledEqnsVector.push_back( DC->compileLateq(eqSigs[i], new Lateq(eqInputs[i], eqOutputs[i])) );
00750 }
00751
00752
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00770 static string calcDocEqnInitial(const string s)
00771 {
00772 string nn;
00773 if(s == "process")
00774 nn = "Y";
00775 else if (s.substr(0,6) == "doceqn")
00776 nn = "Z";
00777 else
00778 nn += toupper(s[0]);
00779 return nn;
00780 }
00781
00782
00790 static void getBoxInputsAndOutputs(const Tree t, int& numInputs, int& numOutputs)
00791 {
00792 if (!getBoxType(t, &numInputs, &numOutputs)) {
00793 cerr << "ERROR during the evaluation of t : " << boxpp(t) << endl;
00794 exit(1);
00795 }
00796
00797 }
00798
00799
00806 static void printDocEqn(Lateq* ltq, ostream& docout)
00807 {
00808 ltq->println(docout);
00809
00810 }
00811
00812
00813
00814
00815
00816
00829 static void printDocDgm(const Tree expr, const char* svgTopDir, ostream& docout, int i)
00830 {
00832 Tree docdgm = evaldocexpr(expr, gExpandedDefList);
00833 if (gErrorCount > 0) {
00834 cerr << "Total of " << gErrorCount << " errors during evaluation of : diagram docdgm = " << boxpp(docdgm) << ";\n";
00835 exit(1);
00836 }
00837
00842 char dgmid[MAXIDCHARS+1];
00843 sprintf(dgmid, "%02d", i);
00844 string thisdgmdir = subst("$0/svg-$1", svgTopDir, dgmid);
00845
00846
00847 drawSchema( docdgm, thisdgmdir.c_str(), "svg" );
00848
00850 char temp[1024];
00851 const string dgmfilename = legalFileName(docdgm, 1024, temp);
00852
00853 docout << "\\begin{figure}[ht!]" << endl;
00854 docout << "\t\\centering" << endl;
00855 docout << "\t\\includegraphics[width=\\textwidth]{" << subst("../svg/svg-$0/", dgmid) << dgmfilename << "}" << endl;
00856 docout << "\t\\caption{block-diagram of \\texttt{" << dgmfilename << "}}" << endl;
00857 docout << "\t\\label{figure" << i << "}" << endl;
00858 docout << "\\end{figure}" << endl << endl;
00859
00861 gDocNoticeFlagMap["nameconflicts"] = true;
00862 gDocNoticeFlagMap["svgdir"] = true;
00863 }
00864
00865
00866
00867
00868
00869
00873 static int makedir(const char* dirname)
00874 {
00875 char buffer[FAUST_PATH_MAX];
00876 gCurrentDir = getcwd (buffer, FAUST_PATH_MAX);
00877
00878 if ( gCurrentDir.c_str() != 0) {
00879 int status = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
00880 if (status == 0 || errno == EEXIST) {
00881 return 0;
00882 }
00883 }
00884 perror("makedir");
00885 exit(errno);
00886 }
00887
00888
00896 static int mkchdir(const char* dirname)
00897 {
00898 char buffer[FAUST_PATH_MAX];
00899 gCurrentDir = getcwd (buffer, FAUST_PATH_MAX);
00900
00901 if ( gCurrentDir.c_str() != 0) {
00902 int status = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
00903 if (status == 0 || errno == EEXIST) {
00904 if (chdir(dirname) == 0) {
00905 return 0;
00906 }
00907 }
00908 }
00909 perror("mkchdir");
00910 exit(errno);
00911 }
00912
00913
00917 static int cholddir ()
00918 {
00919 if (chdir(gCurrentDir.c_str()) == 0) {
00920 return 0;
00921 } else {
00922 perror("cholddir");
00923 exit(errno);
00924 }
00925 }
00926
00927
00931 static void getCurrentDir ()
00932 {
00933 char buffer[FAUST_PATH_MAX];
00934 gCurrentDir = getcwd (buffer, FAUST_PATH_MAX);
00935 }
00936
00937
00941 static istream* openArchFile (const string& filename)
00942 {
00943 istream* file;
00944 getCurrentDir();
00945
00946 if ( (file = open_arch_stream(filename.c_str())) ) {
00947
00948 } else {
00949 cerr << "ERROR : can't open architecture file " << filename << endl;
00950 exit(1);
00951 }
00952 cholddir();
00953 return file;
00954 }
00955
00956
00963 static char* legalFileName(const Tree t, int n, char* dst)
00964 {
00965 Tree id;
00966 int i=0;
00967 if (getDefNameProperty(t, id)) {
00968 const char* src = tree2str(id);
00969 for (i=0; isalnum(src[i]) && i<16; i++) {
00970 dst[i] = src[i];
00971 }
00972 }
00973 dst[i] = 0;
00974 if (strcmp(dst, "process") != 0) {
00975
00976 snprintf(&dst[i], n-i, "-%p", t);
00977 }
00978 return dst;
00979 }
00980
00985 static string calcNumberedName(const char* base, int i)
00986 {
00987 char nb[MAXIDCHARS+1];
00988 sprintf(nb, "%03d", i);
00989 return subst("$0$1", base, nb);
00990 }
00991
00996 static string rmExternalDoubleQuotes(const string& s)
00997 {
00998 size_t i = s.find_first_not_of("\"");
00999 size_t j = s.find_last_not_of("\"");
01000
01001 if ( (i != string::npos) & (j != string::npos) ) {
01002 return s.substr(i, 1+j-i);
01003 } else {
01004 return "";
01005 }
01006 }
01007
01008
01015 static void copyFaustSources(const char* projname, const vector<string>& pathnames)
01016 {
01017 string srcdir = subst("$0/src", projname);
01018
01019 makedir(srcdir.c_str());
01020
01021 for (unsigned int i=0; i< pathnames.size(); i++) {
01022 ifstream src;
01023 ofstream dst;
01024 string faustfile = pathnames[i];
01025 string copy = subst("$0/$1", srcdir, filebasename(faustfile.c_str()));
01026
01027
01028 src.open(faustfile.c_str(), ifstream::in);
01029 dst.open(copy.c_str(), ofstream::out);
01030 string s;
01031 while ( getline(src,s) ) dst << s << endl;
01032 }
01033 }
01034
01035
01036
01037
01038
01039 static void initCompilationDate()
01040 {
01041 time_t now;
01042
01043 time(&now);
01044 gCompilationDate = *localtime(&now);
01045 }
01046
01047 static struct tm* getCompilationDate()
01048 {
01049 initCompilationDate();
01050 return &gCompilationDate;
01051 }
01052