|
FAUST compiler
0.9.9.6b8
|
00001 /************************************************************************ 00002 ************************************************************************ 00003 FAUST compiler 00004 Copyright (C) 2009 GRAME, Centre National de Creation Musicale 00005 --------------------------------------------------------------------- 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 ************************************************************************ 00020 ************************************************************************/ 00021 00022 00023 00024 /***************************************************************************** 00025 ****************************************************************************** 00026 00027 00028 The Documentator Language 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 Globals and prototyping 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 /* Printing functions */ 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 /* Primary sub-functions for <equation> handling */ 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 //static void calcAndSetLtqNames( Tree superEqList ); ///< step 9. 00143 static void mapCompileDocEqnSigs( const vector<Tree>& eqSigs, const vector<int>& eqInputs, const vector<int>& eqOutputs, DocCompiler* DC, vector<Lateq*>& docCompiledEqnsVector ); 00144 00145 /* Secondary sub-functions for <equation> handling */ 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 /* Notice related functions */ 00151 static void initCompilationDate(); 00152 static struct tm* getCompilationDate(); 00153 00154 /* Files functions */ 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 //static void declareAutoDoc(); 00168 00169 00170 00171 /***************************************************************************** 00172 Types of Documentation Elements 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 //string getDocTxt(Tree t) { return hd(t)->branch(0); } 00210 00211 00212 00213 /***************************************************************************** 00214 Main Printing Function for the Documentation 00215 *****************************************************************************/ 00216 00217 00229 void printDoc(const char* projname, const char* docdev, const char* faustversion) 00230 { 00231 gDocDevSuffix = docdev; 00232 00234 //cerr << "Documentator : printDoc : gFaustDirectory = '" << gFaustDirectory << "'" << endl; 00235 //cerr << "Documentator : printDoc : gFaustSuperDirectory = '" << gFaustSuperDirectory << "'" << endl; 00236 //cerr << "Documentator : printDoc : gFaustSuperSuperDirectory = '" << gFaustSuperSuperDirectory << "'" << endl; 00237 //cerr << "Documentator : printDoc : gCurrentDir = '" << gCurrentDir << "'" << endl; 00238 00239 makedir(projname); // create a top directory to store files 00240 00241 string svgTopDir = subst("$0/svg", projname); 00242 makedir(svgTopDir.c_str()); // create a directory to store svg-* subdirectories. 00243 00244 string cppdir = subst("$0/cpp", projname); 00245 makedir(cppdir.c_str()); // create a cpp directory. 00246 00247 string pdfdir = subst("$0/pdf", projname); 00248 makedir(pdfdir.c_str()); // create a pdf directory. 00249 00250 /* Copy all Faust source files into an 'src' sub-directory. */ 00251 vector<string> pathnames = gReader.listSrcFiles(); 00252 copyFaustSources(projname, pathnames); 00253 00254 string texdir = subst("$0/tex", projname); 00255 mkchdir(texdir.c_str()); // create a directory and move into. 00256 00258 ofstream docout(subst("$0.$1", gDocName, docdev).c_str()); 00259 cholddir(); // return to current directory 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 LaTeX basic printing functions of the Documentation 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 //cerr << "Documentator : printfaustlisting : Opening file '" << faustfile << "'" << endl; 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 Main loop : launches prepare, evaluate, and print functions 00423 *****************************************************************************/ 00424 00441 static void printdoccontent(const char* svgTopDir, const vector<Tree>& docVector, const string& faustversion, ostream& docout) 00442 { 00443 //cerr << endl << "Documentator : printdoccontent : " << docVector.size() << " <mdoc> tags read." << endl; 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 //cerr << "Entering into <mdoc> parsing..." << endl; 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); // Directly print registered doc text. 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 //cerr << " ...end of <mdoc> parsing." << endl; 00497 00498 if ( code != docMasterCodeMap.end() && gLstDistributedSwitch ) { 00499 printdocCodeSlices(*code, docout); 00500 } 00501 } 00502 } 00503 00504 00505 00506 /***************************************************************************** 00507 Primary sub-functions for <equation> handling 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 //calcAndSetLtqNames( superEqList ); ///< step 9. (directly in 10.) 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 //cerr << "Documentator : collectDocEqns : " << nbdoceqn << " <equation> tags found." << endl; 00565 } 00566 00567 00575 static void mapEvalDocEqn(const vector<Tree>& eqBoxes, const Tree& env, vector<Tree>& evalEqBoxes) 00576 { 00577 //cerr << "###\n# Documentator : mapEvalDocEqn" << endl; 00578 00579 for ( vector<Tree>::const_iterator eq=eqBoxes.begin(); eq < eqBoxes.end(); eq++) 00580 { 00581 evalEqBoxes.push_back(evaldocexpr( *eq, env )); 00582 } 00583 //cerr << "Documentator : end of mapEvalDocEqn\n---" << endl; 00584 } 00585 00586 00593 static void mapGetEqName(const vector<Tree>& evalEqBoxes, vector<string>& eqNames) 00594 { 00595 //cerr << "###\n# Documentator : mapGetEqName" << endl; 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); // eq name only for bd without inputs 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 //cerr << "Documentator : end of mapGetEqName\n---" << endl; 00611 } 00612 00613 00623 static void calcEqnsNicknames(const vector<string>& eqNames, vector<string>& eqNicknames) 00624 { 00625 //cerr << "###\n# Documentator : calcEqnsNicknames" << endl; 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 // for( vector<string>::iterator it = v.begin(); it < v.end()-1; ++it ) { 00634 // if (init == *it) { 00635 // //cerr << "!! Warning Documentator : calcEqnsNicknames : duplicates \"" << init << "\"" << endl; 00636 // } 00637 // } 00638 eqNicknames.push_back(init); 00639 } 00640 00641 // for( vector<string>::const_iterator eq = eqNames.begin(); eq < eqNames.end(); eq++ ) { 00642 // int c = 0; 00643 // c = count_if(eqNames.begin(), eqNames.end(), bind2nd(equal_to<string>(), *eq)); 00644 // if (c > 0) { 00645 // cerr << "- Duplicate nickname !! " << *eq << endl; 00646 // } else { 00647 // cerr << "(no duplicate) " << *eq << endl; 00648 // } 00649 // } 00650 00651 //cerr << "Documentator : end of calcEqnsNicknames\n---" << endl; 00652 } 00653 00654 00663 static void mapPrepareEqSig(const vector<Tree>& evalEqBoxes, vector<int>& eqInputs, vector<int>& eqOutputs, vector<Tree>& eqSigs) 00664 { 00665 //cerr << "###\n# Documentator : mapPrepareEqSig" << endl; 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 //cerr << numInputs <<" ins and " << numOutputs <<" outs" << endl; 00672 eqInputs.push_back(numInputs); 00673 eqOutputs.push_back(numOutputs); 00674 00675 Tree lsig1 = boxPropagateSig( nil, *eq , makeSigInputList(numInputs) ); 00676 //cerr << "output signals are : " << endl; printSignal(lsig1, stderr); 00677 00678 Tree lsig2 = deBruijn2Sym(lsig1); 00679 Tree lsig3 = simplify(lsig2); 00680 //Tree lsig4 = privatise(lsig3); ///< Un-share tables with multiple writers 00681 Tree lsig4 = docTableConvertion(lsig3); 00682 00683 00684 eqSigs.push_back(lsig4); 00685 } 00686 //cerr << "Documentator : end of mapPrepareEqSig\n---" << endl; 00687 } 00688 00689 00697 static void mapSetSigNickname(const vector<string>& eqNicknames, const vector<int>& eqInputs, const vector<Tree>& eqSigs) 00698 { 00699 //cerr << "###\n# Documentator : mapSetSigNickname" << endl; 00700 00701 // Do nothing for the moment... 00702 // for( unsigned int i=0; i < eqSigs.size(); i++ ) { 00703 // if (eqInputs[i] == 0) // Only "generators" should be finally named with user equation (nick)name. 00704 // setSigListNickName(eqSigs[i], eqNicknames[i]); 00705 // } 00706 //cerr << "Documentator : end of mapSetSigNickname\n---" << endl; 00707 } 00708 00709 00716 static void collectEqSigs(const vector<Tree>& eqSigs, Tree& superEqList) 00717 { 00718 //cerr << "###\n# Documentator : collectEqSigs" << endl; 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 //printSignal(superEqList, stdout, 0); 00726 00727 //cerr << endl << "Documentator : end of collectEqSigs\n---" << endl; 00728 } 00729 00730 00737 static void annotateSuperList(DocCompiler* DC, Tree superEqList) 00738 { 00739 DC->annotate(superEqList); 00740 } 00741 00742 00744 // * #9. Calculated and set lateq (LaTeX equation) names. 00745 // * Note : Transfered into mapCompileDocEqnSigs (DocCompiler::compileMultiSignal). 00746 // */ 00747 //static void calcAndSetLtqNames(Tree superEqList) 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 //cerr << "###\n# Documentator : mapCompileDocEqnSigs" << endl; 00763 00764 for( unsigned int i=0; i < eqSigs.size(); i++ ) { 00765 00766 // docCompiledEqnsVector.push_back( DC->compileMultiSignal(*it, 0) ); 00767 docCompiledEqnsVector.push_back( DC->compileLateq(eqSigs[i], new Lateq(eqInputs[i], eqOutputs[i])) ); 00768 } 00769 00770 //cerr << "Documentator : end of mapCompileDocEqnSigs\n---" << endl; 00771 } 00772 00773 00774 00775 /***************************************************************************** 00776 Secondary sub-functions for <equation> handling 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 //cerr << "Documentator : " << numInputs <<" inputs and " << numOutputs <<" outputs for box : " << boxpp(t) << endl; 00815 } 00816 00817 00824 static void printDocEqn(Lateq* ltq, ostream& docout) 00825 { 00826 ltq->println(docout); 00827 //cerr << "Documentator : printDocEqn : "; ltq->println(cerr); cerr << endl; 00828 } 00829 00830 00831 /***************************************************************************** 00832 Sub-function for <diagram> handling 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 //cerr << "Documentator : printDocDgm : drawSchema in '" << gCurrentDir << "/" << thisdgmdir << "'" << endl; 00864 00865 drawSchema( docdgm, thisdgmdir.c_str(), "svg" ); 00866 00868 char temp[1024]; 00869 const string dgmfilename = legalFileName(docdgm, 1024, temp); 00870 //docout << "figure \\ref{figure" << i << "}"; 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 Other sub-functions 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 //------------------------ dealing with files ------------------------- 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(); // Save the current directory. 01054 //cerr << "Documentator : openArchFile : Opening input file '" << filename << "'" << endl; 01055 if ( (file = open_arch_stream(filename.c_str())) ) { 01056 //cerr << "Documentator : openArchFile : Opening '" << filename << "'" << endl; 01057 } else { 01058 cerr << "ERROR : can't open architecture file " << filename << endl; 01059 exit(1); 01060 } 01061 cholddir(); // Return to current directory. 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 // if it is not process add the hex address to make the name unique 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 //cerr << "Documentator : copyFaustSources : Creating directory '" << srcdir << "'" << endl; 01128 makedir(srcdir.c_str()); // create a directory. 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 //cerr << "Documentator : copyFaustSources : Opening input file '" << faustfile << "'" << endl; 01136 //cerr << "Documentator : copyFaustSources : Opening output file '" << copy << "'" << endl; 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 //------------------------ date managment ------------------------- 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
1.8.0