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 ///< max numbers (characters) to represent ids (e.g. for directories).
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 map<string, string> gDocMathStringMap;
00096 extern bool gDetailsSwitch;
00097 extern bool gStripDocSwitch;
00098 extern string gFaustDirectory;
00099 extern string gFaustSuperDirectory;
00100 extern string gFaustSuperSuperDirectory;
00101 extern string gMasterDocument;
00102 extern string gMasterName;
00103 extern SourceReader gReader;
00104
00105 extern string gDocName;
00106 static const char* gDocDevSuffix;
00107 static string gCurrentDir;
00108 static const string gLatexheaderfilename = "latexheader.tex";
00109
00110 vector<Tree> gDocVector;
00111
00112 static struct tm gCompilationDate;
00113
00114 bool gLstDependenciesSwitch = true;
00115 bool gLstMdocTagsSwitch = true;
00116 bool gLstDistributedSwitch = true;
00117
00118 enum { langEN, langFR, langIT };
00119 string gDocLang;
00120
00121
00122 static void printlatexheader(istream& latexheader, const string& faustversion, ostream& docout);
00123 static void printfaustlistings(ostream& docout);
00124 static void printfaustlisting(string& path, ostream& docout);
00125 static void printlatexfooter(ostream& docout);
00126 static void printdoccontent(const char* svgTopDir, const vector<Tree>& docVector, const string& faustversion, ostream& docout);
00127 static void printfaustdocstamp(const string& faustversion, ostream& docout);
00128 static void printDocEqn(Lateq* ltq, ostream& docout);
00129 static void printDocDgm(const Tree expr, const char* svgTopDir, ostream& docout, int i);
00130 static void printDocMetadata(const Tree expr, ostream& docout);
00131
00132
00133 static void prepareDocEqns( const vector<Tree>& docBoxes, vector<Lateq*>& docCompiledEqnsVector );
00134 static void collectDocEqns( const vector<Tree>& docBoxes, vector<Tree>& eqBoxes );
00135 static void mapEvalDocEqn( const vector<Tree>& eqBoxes, const Tree& env, vector<Tree>& evalEqBoxes );
00136 static void mapGetEqName( const vector<Tree>& evalEqBoxes, vector<string>& eqNames );
00137 static void calcEqnsNicknames( const vector<string>& eqNames, vector<string>& eqNicknames );
00138 static void mapPrepareEqSig( const vector<Tree>& evalEqBoxes, vector<int>& eqInputs, vector<int>& eqOutputs, vector<Tree>& eqSigs );
00139 static void mapSetSigNickname( const vector<string>& eqNicknames, const vector<int>& eqInputs, const vector<Tree>& eqSigs );
00140 static void collectEqSigs( const vector<Tree>& eqSigs, Tree& superEqList );
00141 static void annotateSuperList( DocCompiler* DC, Tree superEqList );
00142
00143 static void mapCompileDocEqnSigs( const vector<Tree>& eqSigs, const vector<int>& eqInputs, const vector<int>& eqOutputs, DocCompiler* DC, vector<Lateq*>& docCompiledEqnsVector );
00144
00145
00146 static string calcNumberedName(const char* base, int i);
00147 static void getBoxInputsAndOutputs(const Tree t, int& numInputs, int& numOutputs);
00148 static string calcDocEqnInitial(const string s);
00149
00150
00151 static void initCompilationDate();
00152 static struct tm* getCompilationDate();
00153
00154
00155 static int cholddir ();
00156 static int mkchdir(const char* dirname);
00157 static int makedir(const char* dirname);
00158 static void getCurrentDir();
00159 static istream* openArchFile (const string& filename);
00160 static char* legalFileName(const Tree t, int n, char* dst);
00161 static string rmExternalDoubleQuotes(const string& s);
00162 static void copyFaustSources(const char* projname, const vector<string>& pathnames);
00163 vector<string>& docCodeSlicer(const string& faustfile, vector<string>& codeSlices);
00164 static void printdocCodeSlices(const string& code, ostream& docout);
00165 static bool doesFileBeginWithCode(const string& faustfile);
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 Sym DOCTXT = symbol ("DocTxt");
00176 Tree docTxt(const char* name) { return tree( DOCTXT, tree(symbol(name)) ); }
00177 bool isDocTxt(Tree t) { return t->node() == Node(DOCTXT); }
00178 bool isDocTxt(Tree t0, const char** str)
00179 {
00180 Tree t1; Sym s;
00181 if ( isTree(t0, DOCTXT, t1) && isSym(t1->node(), &s) ) {
00182 *str = name(s);
00183 return true;
00184 } else {
00185 return false;
00186 }
00187 }
00188
00189 Sym DOCEQN = symbol ("DocEqn");
00190 Tree docEqn(Tree x) { return tree(DOCEQN, x); }
00191 bool isDocEqn(Tree t, Tree& x) { return isTree(t, DOCEQN, x); }
00192
00193 Sym DOCDGM = symbol ("DocDgm");
00194 Tree docDgm(Tree x) { return tree(DOCDGM, x); }
00195 bool isDocDgm(Tree t, Tree& x) { return isTree(t, DOCDGM, x); }
00196
00197 Sym DOCNTC = symbol ("DocNtc");
00198 Tree docNtc() { return tree(DOCNTC); }
00199 bool isDocNtc(Tree t) { return isTree(t, DOCNTC); }
00200
00201 Sym DOCLST = symbol ("DocLst");
00202 Tree docLst() { return tree(DOCLST); }
00203 bool isDocLst(Tree t) { return isTree(t, DOCLST); }
00204
00205 Sym DOCMTD = symbol ("DocMtd");
00206 Tree docMtd(Tree x) { return tree(DOCMTD, x); }
00207 bool isDocMtd(Tree t, Tree& x) { return isTree(t, DOCMTD, x); }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00229 void printDoc(const char* projname, const char* docdev, const char* faustversion)
00230 {
00231 gDocDevSuffix = docdev;
00232
00234
00235
00236
00237
00238
00239 makedir(projname);
00240
00241 string svgTopDir = subst("$0/svg", projname);
00242 makedir(svgTopDir.c_str());
00243
00244 string cppdir = subst("$0/cpp", projname);
00245 makedir(cppdir.c_str());
00246
00247 string pdfdir = subst("$0/pdf", projname);
00248 makedir(pdfdir.c_str());
00249
00250
00251 vector<string> pathnames = gReader.listSrcFiles();
00252 copyFaustSources(projname, pathnames);
00253
00254 string texdir = subst("$0/tex", projname);
00255 mkchdir(texdir.c_str());
00256
00258 ofstream docout(subst("$0.$1", gDocName, docdev).c_str());
00259 cholddir();
00260
00262 loadTranslationFile(gDocLang);
00263
00265 if (gDocVector.empty()) { declareAutoDoc(); }
00266
00268 printfaustdocstamp(faustversion, docout);
00269 istream* latexheader = openArchFile(gLatexheaderfilename);
00270 printlatexheader(*latexheader, faustversion, docout);
00271 printdoccontent(svgTopDir.c_str(), gDocVector, faustversion, docout);
00272 printlatexfooter(docout);
00273 }
00274
00275
00276
00277
00278
00279
00280
00288 static void printlatexheader(istream& latexheader, const string& faustversion, ostream& docout)
00289 {
00290 string s;
00291 while(getline(latexheader, s)) docout << s << endl;
00292
00294 docout << "\\newcommand{\\faustfilename}{" << gMasterDocument << "}" << endl;
00295 docout << "\\newcommand{\\faustdocdir}{" << gMasterName << "-mdoc}" << endl;
00296 docout << "\\newcommand{\\faustprogname}{" << gMasterName << "}" << endl;
00297 docout << "\\newcommand{\\faustversion}{" << faustversion << "}" << endl;
00298 char datebuf [150];
00299 strftime (datebuf, 150, "%B %d, %Y", getCompilationDate());
00300 docout << "\\newcommand{\\faustdocdate}{" << datebuf << "}" << endl;
00301
00302 docout << endl << "\\begin{document}" << endl;
00303 }
00304
00305
00316 static void printDocMetadata(const Tree expr, ostream& docout)
00317 {
00318 if (gMetaDataSet.count(expr)) {
00319 string sep = "";
00320 set<Tree> mset = gMetaDataSet[expr];
00321
00322 for (set<Tree>::iterator j = mset.begin(); j != mset.end(); j++) {
00323 docout << sep << rmExternalDoubleQuotes(tree2str(*j));
00324 sep = ", ";
00325 }
00326 }
00327 }
00328
00329
00336 static void printfaustlistings(ostream& docout)
00337 {
00338 if (gLstDependenciesSwitch) {
00339 vector<string> pathnames = gReader.listSrcFiles();
00340 for (unsigned int i=0; i< pathnames.size(); i++) {
00341 printfaustlisting(pathnames[i], docout);
00342 }
00343 } else {
00344 printfaustlisting(gMasterDocument, docout);
00345 }
00346 }
00347
00348
00356 static void printfaustlisting(string& faustfile, ostream& docout)
00357 {
00358 string s;
00359 ifstream src;
00360
00361
00362 src.open(faustfile.c_str(), ifstream::in);
00363
00364 docout << endl << "\\bigskip\\bigskip" << endl;
00365 docout << "\\begin{lstlisting}[caption=\\texttt{" << filebasename(faustfile.c_str()) << "}]" << endl;
00366
00367 bool isInsideDoc = false;
00368
00369 if (faustfile != "" && src.good()) {
00370 while(getline(src, s)) {
00371 size_t foundopendoc = s.find("<mdoc>");
00372 if (foundopendoc != string::npos && gStripDocSwitch) isInsideDoc = true;
00373
00374 if (isInsideDoc == false)
00375 docout << s << endl;
00376
00377 size_t foundclosedoc = s.find("</mdoc>");
00378 if (foundclosedoc != string::npos && gStripDocSwitch) isInsideDoc = false;
00379 }
00380 } else {
00381 cerr << "ERROR : can't open faust source file " << faustfile << endl;
00382 exit(1);
00383 }
00384
00385 docout << "\\end{lstlisting}" << endl << endl;
00386 }
00387
00388
00394 static void printlatexfooter(ostream& docout)
00395 {
00396 docout << endl << "\\end{document}" << endl << endl;
00397 }
00398
00399
00409 static void printfaustdocstamp(const string& faustversion, ostream& docout)
00410 {
00411 char datebuf [150];
00412 strftime (datebuf, 150, "%c", getCompilationDate());
00413
00414 docout << "%% This documentation was generated with Faust version " << faustversion << endl;
00415 docout << "%% " << datebuf << endl;
00416 docout << "%% http://faust.grame.fr" << endl << endl;
00417 }
00418
00419
00420
00421
00422
00423
00424
00441 static void printdoccontent(const char* svgTopDir, const vector<Tree>& docVector, const string& faustversion, ostream& docout)
00442 {
00443
00444
00446 vector<Lateq*> docCompiledEqnsVector;
00447 prepareDocEqns( docVector, docCompiledEqnsVector );
00448 vector<Lateq*>::iterator eqn_it = docCompiledEqnsVector.begin();
00449
00450 int dgmIndex = 1;
00451
00452 vector<string> docMasterCodeMap;
00453 docMasterCodeMap = docCodeSlicer(gMasterDocument, docMasterCodeMap);
00454
00455 vector<Tree>::const_iterator doc;
00456 vector<string>::const_iterator code;
00457 code = docMasterCodeMap.begin();
00458
00459 if(doesFileBeginWithCode(gMasterDocument) && (! docMasterCodeMap.empty()) && gLstDistributedSwitch ) {
00460 printdocCodeSlices(*code, docout);
00461 code++;
00462 }
00463
00465 for (doc=docVector.begin(); doc<docVector.end(); doc++, code++) {
00466
00467 Tree L = reverse(*doc);
00468
00469
00471 while (isList(L)) {
00472 Tree expr;
00473 if ( isDocEqn(hd(L), expr) ) {
00474 printDocEqn(*eqn_it++, docout);
00475 }
00476 else if ( isDocDgm(hd(L), expr) ) {
00477 printDocDgm(expr, svgTopDir, docout, dgmIndex++);
00478 }
00479 else if ( isDocMtd(hd(L), expr) ) {
00480 printDocMetadata(expr, docout);
00481 }
00482 else if ( isDocTxt(hd(L)) ) {
00483 docout << *hd(L)->branch(0);
00484 }
00485 else if ( isDocNtc(hd(L)) ) {
00486 printDocNotice(faustversion, docout);
00487 }
00488 else if ( isDocLst(hd(L)) ) {
00489 printfaustlistings(docout);
00490 }
00491 else {
00492 cerr << "ERROR : " << *hd(L) << " is not a valid documentation type." << endl;
00493 }
00494 L = tl(L);
00495 }
00496
00497
00498 if ( code != docMasterCodeMap.end() && gLstDistributedSwitch ) {
00499 printdocCodeSlices(*code, docout);
00500 }
00501 }
00502 }
00503
00504
00505
00506
00507
00508
00509
00520 static void prepareDocEqns(const vector<Tree>& docBoxes, vector<Lateq*>& docCompiledEqnsVector)
00521 {
00522 vector<Tree> eqBoxes; collectDocEqns( docBoxes, eqBoxes );
00523
00524 if(! eqBoxes.empty() ) {
00525 vector<Tree> evalEqBoxes; mapEvalDocEqn( eqBoxes, gExpandedDefList, evalEqBoxes );
00526 vector<string> eqNames; mapGetEqName( evalEqBoxes, eqNames );
00527 vector<string> eqNicknames; calcEqnsNicknames( eqNames, eqNicknames );
00528
00529 vector<int> eqInputs;
00530 vector<int> eqOutputs;
00531 vector<Tree> eqSigs; mapPrepareEqSig( evalEqBoxes, eqInputs, eqOutputs, eqSigs );
00532 mapSetSigNickname( eqNicknames, eqInputs, eqSigs );
00533 Tree superEqList; collectEqSigs( eqSigs, superEqList );
00534
00535 DocCompiler* DC = new DocCompiler(0, 0);
00536 annotateSuperList( DC, superEqList );
00537
00538 mapCompileDocEqnSigs( eqSigs, eqInputs, eqOutputs, DC, docCompiledEqnsVector );
00539 }
00540 }
00541
00542
00549 static void collectDocEqns(const vector<Tree>& docBoxes, vector<Tree>& eqBoxes)
00550 {
00551 int nbdoceqn = 0;
00552
00553 for (vector<Tree>::const_iterator doc=docBoxes.begin(); doc<docBoxes.end(); doc++) {
00554 Tree L = reverse(*doc);
00555 Tree expr;
00556 while (isList(L)) {
00557 if ( isDocEqn(hd(L), expr) ) {
00558 eqBoxes.push_back(expr);
00559 nbdoceqn++;
00560 }
00561 L = tl(L);
00562 }
00563 }
00564
00565 }
00566
00567
00575 static void mapEvalDocEqn(const vector<Tree>& eqBoxes, const Tree& env, vector<Tree>& evalEqBoxes)
00576 {
00577
00578
00579 for ( vector<Tree>::const_iterator eq=eqBoxes.begin(); eq < eqBoxes.end(); eq++)
00580 {
00581 evalEqBoxes.push_back(evaldocexpr( *eq, env ));
00582 }
00583
00584 }
00585
00586
00593 static void mapGetEqName(const vector<Tree>& evalEqBoxes, vector<string>& eqNames)
00594 {
00595
00596
00597 int i = 1;
00598 for( vector<Tree>::const_iterator eq = evalEqBoxes.begin(); eq < evalEqBoxes.end(); eq++, i++ ) {
00599 Tree id;
00600 string s;
00601 int n,m; getBoxType(*eq, &n, &m);
00602 if ( n==0 && getDefNameProperty(*eq, id) ) {
00603 s = tree2str(id);
00604 }
00605 else {
00606 s = calcNumberedName("doceqn-", i);
00607 }
00608 eqNames.push_back( s ) ;
00609 }
00610
00611 }
00612
00613
00623 static void calcEqnsNicknames(const vector<string>& eqNames, vector<string>& eqNicknames)
00624 {
00625
00626
00627 vector<string> v;
00628
00629 for( vector<string>::const_iterator eq = eqNames.begin(); eq < eqNames.end(); eq++ ) {
00630 string init = calcDocEqnInitial(*eq);
00631 v.push_back(init);
00633
00634
00635
00636
00637
00638 eqNicknames.push_back(init);
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 }
00653
00654
00663 static void mapPrepareEqSig(const vector<Tree>& evalEqBoxes, vector<int>& eqInputs, vector<int>& eqOutputs, vector<Tree>& eqSigs)
00664 {
00665
00666
00667 for( vector<Tree>::const_iterator eq = evalEqBoxes.begin(); eq < evalEqBoxes.end(); eq++ ) {
00668
00669 int numInputs, numOutputs;
00670 getBoxInputsAndOutputs(*eq, numInputs, numOutputs);
00671
00672 eqInputs.push_back(numInputs);
00673 eqOutputs.push_back(numOutputs);
00674
00675 Tree lsig1 = boxPropagateSig( nil, *eq , makeSigInputList(numInputs) );
00676
00677
00678 Tree lsig2 = deBruijn2Sym(lsig1);
00679 Tree lsig3 = simplify(lsig2);
00680
00681 Tree lsig4 = docTableConvertion(lsig3);
00682
00683
00684 eqSigs.push_back(lsig4);
00685 }
00686
00687 }
00688
00689
00697 static void mapSetSigNickname(const vector<string>& eqNicknames, const vector<int>& eqInputs, const vector<Tree>& eqSigs)
00698 {
00699
00700
00701
00702
00703
00704
00705
00706
00707 }
00708
00709
00716 static void collectEqSigs(const vector<Tree>& eqSigs, Tree& superEqList)
00717 {
00718
00719
00720 superEqList = nil;
00721
00722 for( vector<Tree>::const_iterator it = eqSigs.begin(); it < eqSigs.end(); ++it ) {
00723 superEqList = cons( *it, superEqList );
00724 }
00725
00726
00727
00728 }
00729
00730
00737 static void annotateSuperList(DocCompiler* DC, Tree superEqList)
00738 {
00739 DC->annotate(superEqList);
00740 }
00741
00742
00744
00745
00746
00747
00748
00749
00750
00751
00752
00760 static void mapCompileDocEqnSigs(const vector<Tree>& eqSigs, const vector<int>& eqInputs, const vector<int>& eqOutputs, DocCompiler* DC, vector<Lateq*>& docCompiledEqnsVector)
00761 {
00762
00763
00764 for( unsigned int i=0; i < eqSigs.size(); i++ ) {
00765
00766
00767 docCompiledEqnsVector.push_back( DC->compileLateq(eqSigs[i], new Lateq(eqInputs[i], eqOutputs[i])) );
00768 }
00769
00770
00771 }
00772
00773
00774
00775
00776
00777
00778
00779
00788 static string calcDocEqnInitial(const string s)
00789 {
00790 string nn;
00791 if(s == "process")
00792 nn = "Y";
00793 else if (s.substr(0,6) == "doceqn")
00794 nn = "Z";
00795 else
00796 nn += toupper(s[0]);
00797 return nn;
00798 }
00799
00800
00808 static void getBoxInputsAndOutputs(const Tree t, int& numInputs, int& numOutputs)
00809 {
00810 if (!getBoxType(t, &numInputs, &numOutputs)) {
00811 cerr << "ERROR during the evaluation of t : " << boxpp(t) << endl;
00812 exit(1);
00813 }
00814
00815 }
00816
00817
00824 static void printDocEqn(Lateq* ltq, ostream& docout)
00825 {
00826 ltq->println(docout);
00827
00828 }
00829
00830
00831
00832
00833
00834
00847 static void printDocDgm(const Tree expr, const char* svgTopDir, ostream& docout, int i)
00848 {
00850 Tree docdgm = evaldocexpr(expr, gExpandedDefList);
00851 if (gErrorCount > 0) {
00852 cerr << "Total of " << gErrorCount << " errors during evaluation of : diagram docdgm = " << boxpp(docdgm) << ";\n";
00853 exit(1);
00854 }
00855
00860 char dgmid[MAXIDCHARS+1];
00861 sprintf(dgmid, "%02d", i);
00862 string thisdgmdir = subst("$0/svg-$1", svgTopDir, dgmid);
00863
00864
00865 drawSchema( docdgm, thisdgmdir.c_str(), "svg" );
00866
00868 char temp[1024];
00869 const string dgmfilename = legalFileName(docdgm, 1024, temp);
00870
00871 docout << "\\begin{figure}[ht!]" << endl;
00872 docout << "\t\\centering" << endl;
00873 docout << "\t\\includegraphics[width=\\textwidth]{" << subst("../svg/svg-$0/", dgmid) << dgmfilename << "}" << endl;
00874 docout << "\t\\caption{" << gDocMathStringMap["dgmcaption"] << " \\texttt{" << dgmfilename << "}}" << endl;
00875 docout << "\t\\label{figure" << i << "}" << endl;
00876 docout << "\\end{figure}" << endl << endl;
00877
00879 gDocNoticeFlagMap["nameconflicts"] = true;
00880 gDocNoticeFlagMap["svgdir"] = true;
00881 }
00882
00883
00884
00885
00886
00887
00888
00889
00896 vector<string>& docCodeSlicer(const string& faustfile, vector<string>& codeSlices)
00897 {
00898 string s;
00899 ifstream src;
00900 src.open(faustfile.c_str(), ifstream::in);
00901 string tmp = "";
00902
00903 bool isInsideDoc = false;
00904
00905 if (faustfile != "" && src.good()) {
00906 while(getline(src, s)) {
00907 size_t foundopendoc = s.find("<mdoc>");
00908
00909 if (foundopendoc != string::npos) {
00910 if (isInsideDoc == false) {
00911 if (! tmp.empty() ) {
00912 codeSlices.push_back(tmp); }
00913 tmp = "";
00914 }
00915 isInsideDoc = true;
00916 }
00917
00918 if (isInsideDoc == false) {
00919 tmp += s + '\n';
00920 }
00921
00922 size_t foundclosedoc = s.find("</mdoc>");
00923 if (foundclosedoc != string::npos) isInsideDoc = false;
00924 }
00925 } else {
00926 cerr << "ERROR : can't open faust source file " << faustfile << endl;
00927 exit(1);
00928 }
00929 return codeSlices;
00930 }
00931
00932
00939 static void printdocCodeSlices(const string& code, ostream& docout)
00940 {
00941 if ( ! code.empty() ) {
00942 docout << endl << "\\begin{lstlisting}[numbers=none, frame=none, basicstyle=\\small\\ttfamily, backgroundcolor=\\color{yobg}]" << endl;
00943 docout << code << endl;
00944 docout << "\\end{lstlisting}" << endl << endl;
00945 }
00946 }
00947
00948
00954 static bool doesFileBeginWithCode(const string& faustfile)
00955 {
00956 string s;
00957 ifstream src;
00958 src.open(faustfile.c_str(), ifstream::in);
00959
00960 if (faustfile != "" && src.good()) {
00961 getline(src, s);
00962 size_t foundopendoc = s.find("<mdoc>");
00963 if(int(foundopendoc)==0) {
00964 return false;
00965 } else {
00966 return true;
00967 }
00968 } else {
00969 cerr << "ERROR : can't open faust source file " << faustfile << endl;
00970 exit(1);
00971 }
00972 }
00973
00974
00975
00976
00977
00978
00982 static int makedir(const char* dirname)
00983 {
00984 char buffer[FAUST_PATH_MAX];
00985 gCurrentDir = getcwd (buffer, FAUST_PATH_MAX);
00986
00987 if ( gCurrentDir.c_str() != 0) {
00988 int status = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
00989 if (status == 0 || errno == EEXIST) {
00990 return 0;
00991 }
00992 }
00993 perror("makedir");
00994 exit(errno);
00995 }
00996
00997
01005 static int mkchdir(const char* dirname)
01006 {
01007 char buffer[FAUST_PATH_MAX];
01008 gCurrentDir = getcwd (buffer, FAUST_PATH_MAX);
01009
01010 if ( gCurrentDir.c_str() != 0) {
01011 int status = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
01012 if (status == 0 || errno == EEXIST) {
01013 if (chdir(dirname) == 0) {
01014 return 0;
01015 }
01016 }
01017 }
01018 perror("mkchdir");
01019 exit(errno);
01020 }
01021
01022
01026 static int cholddir ()
01027 {
01028 if (chdir(gCurrentDir.c_str()) == 0) {
01029 return 0;
01030 } else {
01031 perror("cholddir");
01032 exit(errno);
01033 }
01034 }
01035
01036
01040 static void getCurrentDir ()
01041 {
01042 char buffer[FAUST_PATH_MAX];
01043 gCurrentDir = getcwd (buffer, FAUST_PATH_MAX);
01044 }
01045
01046
01050 static istream* openArchFile (const string& filename)
01051 {
01052 istream* file;
01053 getCurrentDir();
01054
01055 if ( (file = open_arch_stream(filename.c_str())) ) {
01056
01057 } else {
01058 cerr << "ERROR : can't open architecture file " << filename << endl;
01059 exit(1);
01060 }
01061 cholddir();
01062 return file;
01063 }
01064
01065
01072 static char* legalFileName(const Tree t, int n, char* dst)
01073 {
01074 Tree id;
01075 int i=0;
01076 if (getDefNameProperty(t, id)) {
01077 const char* src = tree2str(id);
01078 for (i=0; isalnum(src[i]) && i<16; i++) {
01079 dst[i] = src[i];
01080 }
01081 }
01082 dst[i] = 0;
01083 if (strcmp(dst, "process") != 0) {
01084
01085 snprintf(&dst[i], n-i, "-%p", t);
01086 }
01087 return dst;
01088 }
01089
01094 static string calcNumberedName(const char* base, int i)
01095 {
01096 char nb[MAXIDCHARS+1];
01097 sprintf(nb, "%03d", i);
01098 return subst("$0$1", base, nb);
01099 }
01100
01105 static string rmExternalDoubleQuotes(const string& s)
01106 {
01107 size_t i = s.find_first_not_of("\"");
01108 size_t j = s.find_last_not_of("\"");
01109
01110 if ( (i != string::npos) & (j != string::npos) ) {
01111 return s.substr(i, 1+j-i);
01112 } else {
01113 return "";
01114 }
01115 }
01116
01117
01124 static void copyFaustSources(const char* projname, const vector<string>& pathnames)
01125 {
01126 string srcdir = subst("$0/src", projname);
01127
01128 makedir(srcdir.c_str());
01129
01130 for (unsigned int i=0; i< pathnames.size(); i++) {
01131 ifstream src;
01132 ofstream dst;
01133 string faustfile = pathnames[i];
01134 string copy = subst("$0/$1", srcdir, filebasename(faustfile.c_str()));
01135
01136
01137 src.open(faustfile.c_str(), ifstream::in);
01138 dst.open(copy.c_str(), ofstream::out);
01139 string s;
01140 while ( getline(src,s) ) dst << s << endl;
01141 }
01142 }
01143
01144
01145
01146
01147
01148 static void initCompilationDate()
01149 {
01150 time_t now;
01151
01152 time(&now);
01153 gCompilationDate = *localtime(&now);
01154 }
01155
01156 static struct tm* getCompilationDate()
01157 {
01158 initCompilationDate();
01159 return &gCompilationDate;
01160 }
01161