FAUST compiler  0.9.9.6b8
doc.cpp
Go to the documentation of this file.
1 /************************************************************************
2  ************************************************************************
3  FAUST compiler
4  Copyright (C) 2009 GRAME, Centre National de Creation Musicale
5  ---------------------------------------------------------------------
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  ************************************************************************
20  ************************************************************************/
21 
22 
23 
24 /*****************************************************************************
25  ******************************************************************************
26 
27 
28  The Documentator Language
29 
30 
31  ******************************************************************************
32  *****************************************************************************/
33 
34 
43 #include <stdio.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <sys/stat.h>
47 #include <time.h>
48 #include <algorithm>
49 #include <functional>
50 
51 #include <iostream>
52 #include <fstream>
53 #include <sstream>
54 
55 #include <map>
56 #include <string>
57 #include <vector>
58 
59 #include "ppbox.hh"
60 #include "prim2.hh"
61 #include "doc.hh"
62 #include "eval.hh"
63 #include "errormsg.hh"
64 #include "doc_Text.hh"
65 #include "sigprint.hh"
66 #include "propagate.hh"
67 #include "enrobage.hh"
68 #include "drawschema.hh"
69 #include "names.hh"
70 #include "simplify.hh"
71 #include "privatise.hh"
72 #include "recursivness.hh"
73 #include "sourcereader.hh"
74 #include "lateq.hh"
75 #include "doc_compile.hh"
76 #include "doc_lang.hh"
77 #include "doc_notice.hh"
78 #include "doc_autodoc.hh"
79 #include "compatibility.hh"
80 #include "files.hh"
81 
82 
83 #define MAXIDCHARS 5
84 
85 using namespace std ;
86 
87 
88 /*****************************************************************************
89  Globals and prototyping
90  *****************************************************************************/
91 
92 extern Tree gExpandedDefList;
93 extern map<Tree, set<Tree> > gMetaDataSet;
94 extern map<string, string> gDocMetadatasStringMap;
95 extern map<string, string> gDocMathStringMap;
96 extern bool gDetailsSwitch;
97 extern bool gStripDocSwitch;
98 extern string gFaustDirectory;
99 extern string gFaustSuperDirectory;
100 extern string gFaustSuperSuperDirectory;
101 extern string gMasterDocument;
102 extern string gMasterName;
103 extern SourceReader gReader;
104 
105 extern string gDocName;
106 static const char* gDocDevSuffix;
107 static const string gLatexheaderfilename = "latexheader.tex";
108 
109 vector<Tree> gDocVector;
110 
111 static struct tm gCompilationDate;
112 
114 bool gLstMdocTagsSwitch = true;
116 
117 enum { langEN, langFR, langIT };
118 string gDocLang;
119 
120 /* Printing functions */
121 static void printlatexheader(istream& latexheader, const string& faustversion, ostream& docout);
122 static void printfaustlistings(ostream& docout);
123 static void printfaustlisting(string& path, ostream& docout);
124 static void printlatexfooter(ostream& docout);
125 static void printdoccontent(const char* svgTopDir, const vector<Tree>& docVector, const string& faustversion, ostream& docout);
126 static void printfaustdocstamp(const string& faustversion, ostream& docout);
127 static void printDocEqn(Lateq* ltq, ostream& docout);
128 static void printDocDgm(const Tree expr, const char* svgTopDir, ostream& docout, int i);
129 static void printDocMetadata(const Tree expr, ostream& docout);
130 
131 /* Primary sub-functions for <equation> handling */
132 static void prepareDocEqns( const vector<Tree>& docBoxes, vector<Lateq*>& docCompiledEqnsVector );
133 static void collectDocEqns( const vector<Tree>& docBoxes, vector<Tree>& eqBoxes );
134 static void mapEvalDocEqn( const vector<Tree>& eqBoxes, const Tree& env, vector<Tree>& evalEqBoxes );
135 static void mapGetEqName( const vector<Tree>& evalEqBoxes, vector<string>& eqNames );
136 static void calcEqnsNicknames( const vector<string>& eqNames, vector<string>& eqNicknames );
137 static void mapPrepareEqSig( const vector<Tree>& evalEqBoxes, vector<int>& eqInputs, vector<int>& eqOutputs, vector<Tree>& eqSigs );
138 static void mapSetSigNickname( const vector<string>& eqNicknames, const vector<int>& eqInputs, const vector<Tree>& eqSigs );
139 static void collectEqSigs( const vector<Tree>& eqSigs, Tree& superEqList );
140 static void annotateSuperList( DocCompiler* DC, Tree superEqList );
141 //static void calcAndSetLtqNames( Tree superEqList ); ///< step 9.
142 static void mapCompileDocEqnSigs( const vector<Tree>& eqSigs, const vector<int>& eqInputs, const vector<int>& eqOutputs, DocCompiler* DC, vector<Lateq*>& docCompiledEqnsVector );
143 
144 /* Secondary sub-functions for <equation> handling */
145 static string calcNumberedName(const char* base, int i);
146 static void getBoxInputsAndOutputs(const Tree t, int& numInputs, int& numOutputs);
147 static string calcDocEqnInitial(const string s);
148 
149 /* Notice related functions */
150 static void initCompilationDate();
151 static struct tm* getCompilationDate();
152 
153 /* Files functions */
154 static istream* openArchFile (const string& filename);
155 static char* legalFileName(const Tree t, int n, char* dst);
156 static string rmExternalDoubleQuotes(const string& s);
157 static void copyFaustSources(const char* projname, const vector<string>& pathnames);
158 vector<string>& docCodeSlicer(const string& faustfile, vector<string>& codeSlices);
159 static void printdocCodeSlices(const string& code, ostream& docout);
160 static bool doesFileBeginWithCode(const string& faustfile);
161 
162 //static void declareAutoDoc();
163 
164 
165 
166 /*****************************************************************************
167  Types of Documentation Elements
168  *****************************************************************************/
169 
170 Sym DOCTXT = symbol ("DocTxt");
171 Tree docTxt(const char* name) { return tree( DOCTXT, tree(symbol(name)) ); }
172 bool isDocTxt(Tree t) { return t->node() == Node(DOCTXT); }
173 bool isDocTxt(Tree t0, const char** str)
174 {
175  Tree t1; Sym s;
176  if ( isTree(t0, DOCTXT, t1) && isSym(t1->node(), &s) ) {
177  *str = name(s);
178  return true;
179  } else {
180  return false;
181  }
182 }
183 
184 Sym DOCEQN = symbol ("DocEqn");
185 Tree docEqn(Tree x) { return tree(DOCEQN, x); }
186 bool isDocEqn(Tree t, Tree& x) { return isTree(t, DOCEQN, x); }
187 
188 Sym DOCDGM = symbol ("DocDgm");
189 Tree docDgm(Tree x) { return tree(DOCDGM, x); }
190 bool isDocDgm(Tree t, Tree& x) { return isTree(t, DOCDGM, x); }
191 
192 Sym DOCNTC = symbol ("DocNtc");
193 Tree docNtc() { return tree(DOCNTC); }
194 bool isDocNtc(Tree t) { return isTree(t, DOCNTC); }
195 
196 Sym DOCLST = symbol ("DocLst");
197 Tree docLst() { return tree(DOCLST); }
198 bool isDocLst(Tree t) { return isTree(t, DOCLST); }
199 
200 Sym DOCMTD = symbol ("DocMtd");
201 Tree docMtd(Tree x) { return tree(DOCMTD, x); }
202 bool isDocMtd(Tree t, Tree& x) { return isTree(t, DOCMTD, x); }
203 
204 //string getDocTxt(Tree t) { return hd(t)->branch(0); }
205 
206 
207 
208 /*****************************************************************************
209  Main Printing Function for the Documentation
210  *****************************************************************************/
211 
212 
224 void printDoc(const char* projname, const char* docdev, const char* faustversion)
225 {
226  gDocDevSuffix = docdev;
227 
229  //cerr << "Documentator : printDoc : gFaustDirectory = '" << gFaustDirectory << "'" << endl;
230  //cerr << "Documentator : printDoc : gFaustSuperDirectory = '" << gFaustSuperDirectory << "'" << endl;
231  //cerr << "Documentator : printDoc : gFaustSuperSuperDirectory = '" << gFaustSuperSuperDirectory << "'" << endl;
232  //cerr << "Documentator : printDoc : gCurrentDir = '" << gCurrentDir << "'" << endl;
233 
234  makedir(projname); // create a top directory to store files
235 
236  string svgTopDir = subst("$0/svg", projname);
237  makedir(svgTopDir.c_str()); // create a directory to store svg-* subdirectories.
238 
239  string cppdir = subst("$0/cpp", projname);
240  makedir(cppdir.c_str()); // create a cpp directory.
241 
242  string pdfdir = subst("$0/pdf", projname);
243  makedir(pdfdir.c_str()); // create a pdf directory.
244 
245  /* Copy all Faust source files into an 'src' sub-directory. */
246  vector<string> pathnames = gReader.listSrcFiles();
247  copyFaustSources(projname, pathnames);
248 
249  string texdir = subst("$0/tex", projname);
250  mkchdir(texdir.c_str()); // create a directory and move into.
251 
253  ofstream docout(subst("$0.$1", gDocName, docdev).c_str());
254  cholddir(); // return to current directory
255 
258 
260  if (gDocVector.empty()) { declareAutoDoc(); }
261 
263  printfaustdocstamp(faustversion, docout);
264  istream* latexheader = openArchFile(gLatexheaderfilename);
265  printlatexheader(*latexheader, faustversion, docout);
266  printdoccontent(svgTopDir.c_str(), gDocVector, faustversion, docout);
267  printlatexfooter(docout);
268 }
269 
270 
271 
272 /*****************************************************************************
273  LaTeX basic printing functions of the Documentation
274  *****************************************************************************/
275 
283 static void printlatexheader(istream& latexheader, const string& faustversion, ostream& docout)
284 {
285  string s;
286  while(getline(latexheader, s)) docout << s << endl;
287 
289  docout << "\\newcommand{\\faustfilename}{" << gMasterDocument << "}" << endl;
290  docout << "\\newcommand{\\faustdocdir}{" << gMasterName << "-mdoc}" << endl;
291  docout << "\\newcommand{\\faustprogname}{" << gMasterName << "}" << endl;
292  docout << "\\newcommand{\\faustversion}{" << faustversion << "}" << endl;
293  char datebuf [150];
294  strftime (datebuf, 150, "%B %d, %Y", getCompilationDate());
295  docout << "\\newcommand{\\faustdocdate}{" << datebuf << "}" << endl;
296 
297  docout << endl << "\\begin{document}" << endl;
298 }
299 
300 
311 static void printDocMetadata(const Tree expr, ostream& docout)
312 {
313  if (gMetaDataSet.count(expr)) {
314  string sep = "";
315  set<Tree> mset = gMetaDataSet[expr];
316 
317  for (set<Tree>::iterator j = mset.begin(); j != mset.end(); j++) {
318  docout << sep << rmExternalDoubleQuotes(tree2str(*j));
319  sep = ", ";
320  }
321  }
322 }
323 
324 
331 static void printfaustlistings(ostream& docout)
332 {
334  vector<string> pathnames = gReader.listSrcFiles();
335  for (unsigned int i=0; i< pathnames.size(); i++) {
336  printfaustlisting(pathnames[i], docout);
337  }
338  } else {
340  }
341 }
342 
343 
351 static void printfaustlisting(string& faustfile, ostream& docout)
352 {
353  string s;
354  ifstream src;
355 
356  //cerr << "Documentator : printfaustlisting : Opening file '" << faustfile << "'" << endl;
357  src.open(faustfile.c_str(), ifstream::in);
358 
359  docout << endl << "\\bigskip\\bigskip" << endl;
360  docout << "\\begin{lstlisting}[caption=\\texttt{" << filebasename(faustfile.c_str()) << "}]" << endl;
361 
362  bool isInsideDoc = false;
363 
364  if (faustfile != "" && src.good()) {
365  while(getline(src, s)) {
366  size_t foundopendoc = s.find("<mdoc>");
367  if (foundopendoc != string::npos && gStripDocSwitch) isInsideDoc = true;
368 
369  if (isInsideDoc == false)
370  docout << s << endl;
371 
372  size_t foundclosedoc = s.find("</mdoc>");
373  if (foundclosedoc != string::npos && gStripDocSwitch) isInsideDoc = false;
374  }
375  } else {
376  cerr << "ERROR : can't open faust source file " << faustfile << endl;
377  exit(1);
378  }
379 
380  docout << "\\end{lstlisting}" << endl << endl;
381 }
382 
383 
389 static void printlatexfooter(ostream& docout)
390 {
391  docout << endl << "\\end{document}" << endl << endl;
392 }
393 
394 
404 static void printfaustdocstamp(const string& faustversion, ostream& docout)
405 {
406  char datebuf [150];
407  strftime (datebuf, 150, "%c", getCompilationDate());
408 
409  docout << "%% This documentation was generated with Faust version " << faustversion << endl;
410  docout << "%% " << datebuf << endl;
411  docout << "%% http://faust.grame.fr" << endl << endl;
412 }
413 
414 
415 
416 /*****************************************************************************
417  Main loop : launches prepare, evaluate, and print functions
418  *****************************************************************************/
419 
436 static void printdoccontent(const char* svgTopDir, const vector<Tree>& docVector, const string& faustversion, ostream& docout)
437 {
438  //cerr << endl << "Documentator : printdoccontent : " << docVector.size() << " <mdoc> tags read." << endl;
439 
441  vector<Lateq*> docCompiledEqnsVector;
442  prepareDocEqns( docVector, docCompiledEqnsVector );
443  vector<Lateq*>::iterator eqn_it = docCompiledEqnsVector.begin();
444 
445  int dgmIndex = 1;
446 
447  vector<string> docMasterCodeMap;
448  docMasterCodeMap = docCodeSlicer(gMasterDocument, docMasterCodeMap);
449 
450  vector<Tree>::const_iterator doc;
451  vector<string>::const_iterator code;
452  code = docMasterCodeMap.begin();
453 
454  if(doesFileBeginWithCode(gMasterDocument) && (! docMasterCodeMap.empty()) && gLstDistributedSwitch ) {
455  printdocCodeSlices(*code, docout);
456  code++;
457  }
458 
460  for (doc=docVector.begin(); doc<docVector.end(); doc++, code++) {
461 
462  Tree L = reverse(*doc);
463  //cerr << "Entering into <mdoc> parsing..." << endl;
464 
466  while (isList(L)) {
467  Tree expr;
468  if ( isDocEqn(hd(L), expr) ) {
469  printDocEqn(*eqn_it++, docout);
470  }
471  else if ( isDocDgm(hd(L), expr) ) {
472  printDocDgm(expr, svgTopDir, docout, dgmIndex++);
473  }
474  else if ( isDocMtd(hd(L), expr) ) {
475  printDocMetadata(expr, docout);
476  }
477  else if ( isDocTxt(hd(L)) ) {
478  docout << *hd(L)->branch(0); // Directly print registered doc text.
479  }
480  else if ( isDocNtc(hd(L)) ) {
481  printDocNotice(faustversion, docout);
482  }
483  else if ( isDocLst(hd(L)) ) {
484  printfaustlistings(docout);
485  }
486  else {
487  cerr << "ERROR : " << *hd(L) << " is not a valid documentation type." << endl;
488  }
489  L = tl(L);
490  }
491  //cerr << " ...end of <mdoc> parsing." << endl;
492 
493  if ( code != docMasterCodeMap.end() && gLstDistributedSwitch ) {
494  printdocCodeSlices(*code, docout);
495  }
496  }
497 }
498 
499 
500 
501 /*****************************************************************************
502  Primary sub-functions for <equation> handling
503  *****************************************************************************/
504 
515 static void prepareDocEqns(const vector<Tree>& docBoxes, vector<Lateq*>& docCompiledEqnsVector)
516 {
517  vector<Tree> eqBoxes; collectDocEqns( docBoxes, eqBoxes );
518 
519  if(! eqBoxes.empty() ) {
520  vector<Tree> evalEqBoxes; mapEvalDocEqn( eqBoxes, gExpandedDefList, evalEqBoxes );
521  vector<string> eqNames; mapGetEqName( evalEqBoxes, eqNames );
522  vector<string> eqNicknames; calcEqnsNicknames( eqNames, eqNicknames );
523 
524  vector<int> eqInputs;
525  vector<int> eqOutputs;
526  vector<Tree> eqSigs; mapPrepareEqSig( evalEqBoxes, eqInputs, eqOutputs, eqSigs );
527  mapSetSigNickname( eqNicknames, eqInputs, eqSigs );
528  Tree superEqList; collectEqSigs( eqSigs, superEqList );
529 
530  DocCompiler* DC = new DocCompiler(0, 0);
531  annotateSuperList( DC, superEqList );
532  //calcAndSetLtqNames( superEqList ); ///< step 9. (directly in 10.)
533  mapCompileDocEqnSigs( eqSigs, eqInputs, eqOutputs, DC, docCompiledEqnsVector );
534  }
535 }
536 
537 
544 static void collectDocEqns(const vector<Tree>& docBoxes, vector<Tree>& eqBoxes)
545 {
546  int nbdoceqn = 0;
547 
548  for (vector<Tree>::const_iterator doc=docBoxes.begin(); doc<docBoxes.end(); doc++) {
549  Tree L = reverse(*doc);
550  Tree expr;
551  while (isList(L)) {
552  if ( isDocEqn(hd(L), expr) ) {
553  eqBoxes.push_back(expr);
554  nbdoceqn++;
555  }
556  L = tl(L);
557  }
558  }
559  //cerr << "Documentator : collectDocEqns : " << nbdoceqn << " <equation> tags found." << endl;
560 }
561 
562 
570 static void mapEvalDocEqn(const vector<Tree>& eqBoxes, const Tree& env, vector<Tree>& evalEqBoxes)
571 {
572  //cerr << "###\n# Documentator : mapEvalDocEqn" << endl;
573 
574  for ( vector<Tree>::const_iterator eq=eqBoxes.begin(); eq < eqBoxes.end(); eq++)
575  {
576  evalEqBoxes.push_back(evaldocexpr( *eq, env ));
577  }
578  //cerr << "Documentator : end of mapEvalDocEqn\n---" << endl;
579 }
580 
581 
588 static void mapGetEqName(const vector<Tree>& evalEqBoxes, vector<string>& eqNames)
589 {
590  //cerr << "###\n# Documentator : mapGetEqName" << endl;
591 
592  int i = 1;
593  for( vector<Tree>::const_iterator eq = evalEqBoxes.begin(); eq < evalEqBoxes.end(); eq++, i++ ) {
594  Tree id;
595  string s;
596  int n,m; getBoxType(*eq, &n, &m); // eq name only for bd without inputs
597  if ( n==0 && getDefNameProperty(*eq, id) ) {
598  s = tree2str(id);
599  }
600  else {
601  s = calcNumberedName("doceqn-", i);
602  }
603  eqNames.push_back( s ) ;
604  }
605  //cerr << "Documentator : end of mapGetEqName\n---" << endl;
606 }
607 
608 
618 static void calcEqnsNicknames(const vector<string>& eqNames, vector<string>& eqNicknames)
619 {
620  //cerr << "###\n# Documentator : calcEqnsNicknames" << endl;
621 
622  vector<string> v;
623 
624  for( vector<string>::const_iterator eq = eqNames.begin(); eq < eqNames.end(); eq++ ) {
625  string init = calcDocEqnInitial(*eq);
626  v.push_back(init);
628 // for( vector<string>::iterator it = v.begin(); it < v.end()-1; ++it ) {
629 // if (init == *it) {
630 // //cerr << "!! Warning Documentator : calcEqnsNicknames : duplicates \"" << init << "\"" << endl;
631 // }
632 // }
633  eqNicknames.push_back(init);
634  }
635 
636 // for( vector<string>::const_iterator eq = eqNames.begin(); eq < eqNames.end(); eq++ ) {
637 // int c = 0;
638 // c = count_if(eqNames.begin(), eqNames.end(), bind2nd(equal_to<string>(), *eq));
639 // if (c > 0) {
640 // cerr << "- Duplicate nickname !! " << *eq << endl;
641 // } else {
642 // cerr << "(no duplicate) " << *eq << endl;
643 // }
644 // }
645 
646  //cerr << "Documentator : end of calcEqnsNicknames\n---" << endl;
647 }
648 
649 
658 static void mapPrepareEqSig(const vector<Tree>& evalEqBoxes, vector<int>& eqInputs, vector<int>& eqOutputs, vector<Tree>& eqSigs)
659 {
660  //cerr << "###\n# Documentator : mapPrepareEqSig" << endl;
661 
662  for( vector<Tree>::const_iterator eq = evalEqBoxes.begin(); eq < evalEqBoxes.end(); eq++ ) {
663 
664  int numInputs, numOutputs;
665  getBoxInputsAndOutputs(*eq, numInputs, numOutputs);
666  //cerr << numInputs <<" ins and " << numOutputs <<" outs" << endl;
667  eqInputs.push_back(numInputs);
668  eqOutputs.push_back(numOutputs);
669 
670  Tree lsig1 = boxPropagateSig( nil, *eq , makeSigInputList(numInputs) );
671  //cerr << "output signals are : " << endl; printSignal(lsig1, stderr);
672 
673  Tree lsig2 = deBruijn2Sym(lsig1);
674  Tree lsig3 = simplify(lsig2);
675  //Tree lsig4 = privatise(lsig3); ///< Un-share tables with multiple writers
676  Tree lsig4 = docTableConvertion(lsig3);
677 
679  eqSigs.push_back(lsig4);
680  }
681  //cerr << "Documentator : end of mapPrepareEqSig\n---" << endl;
682 }
683 
684 
692 static void mapSetSigNickname(const vector<string>& eqNicknames, const vector<int>& eqInputs, const vector<Tree>& eqSigs)
693 {
694  //cerr << "###\n# Documentator : mapSetSigNickname" << endl;
695 
696 // Do nothing for the moment...
697 // for( unsigned int i=0; i < eqSigs.size(); i++ ) {
698 // if (eqInputs[i] == 0) // Only "generators" should be finally named with user equation (nick)name.
699 // setSigListNickName(eqSigs[i], eqNicknames[i]);
700 // }
701  //cerr << "Documentator : end of mapSetSigNickname\n---" << endl;
702 }
703 
704 
711 static void collectEqSigs(const vector<Tree>& eqSigs, Tree& superEqList)
712 {
713  //cerr << "###\n# Documentator : collectEqSigs" << endl;
714 
715  superEqList = nil;
716 
717  for( vector<Tree>::const_iterator it = eqSigs.begin(); it < eqSigs.end(); ++it ) {
718  superEqList = cons( *it, superEqList );
719  }
720  //printSignal(superEqList, stdout, 0);
721 
722  //cerr << endl << "Documentator : end of collectEqSigs\n---" << endl;
723 }
724 
725 
732 static void annotateSuperList(DocCompiler* DC, Tree superEqList)
733 {
734  DC->annotate(superEqList);
735 }
736 
737 
739 // * #9. Calculated and set lateq (LaTeX equation) names.
740 // * Note : Transfered into mapCompileDocEqnSigs (DocCompiler::compileMultiSignal).
741 // */
742 //static void calcAndSetLtqNames(Tree superEqList)
743 //{
744 //
745 //}
746 
747 
755 static void mapCompileDocEqnSigs(const vector<Tree>& eqSigs, const vector<int>& eqInputs, const vector<int>& eqOutputs, DocCompiler* DC, vector<Lateq*>& docCompiledEqnsVector)
756 {
757  //cerr << "###\n# Documentator : mapCompileDocEqnSigs" << endl;
758 
759  for( unsigned int i=0; i < eqSigs.size(); i++ ) {
760 
761  // docCompiledEqnsVector.push_back( DC->compileMultiSignal(*it, 0) );
762  docCompiledEqnsVector.push_back( DC->compileLateq(eqSigs[i], new Lateq(eqInputs[i], eqOutputs[i])) );
763  }
764 
765  //cerr << "Documentator : end of mapCompileDocEqnSigs\n---" << endl;
766 }
767 
768 
769 
770 /*****************************************************************************
771  Secondary sub-functions for <equation> handling
772  *****************************************************************************/
773 
774 
783 static string calcDocEqnInitial(const string s)
784 {
785  string nn;
786  if(s == "process")
787  nn = "Y";
788  else if (s.substr(0,6) == "doceqn")
789  nn = "Z";
790  else
791  nn += toupper(s[0]);
792  return nn;
793 }
794 
795 
803 static void getBoxInputsAndOutputs(const Tree t, int& numInputs, int& numOutputs)
804 {
805  if (!getBoxType(t, &numInputs, &numOutputs)) {
806  cerr << "ERROR during the evaluation of t : " << boxpp(t) << endl;
807  exit(1);
808  }
809  //cerr << "Documentator : " << numInputs <<" inputs and " << numOutputs <<" outputs for box : " << boxpp(t) << endl;
810 }
811 
812 
819 static void printDocEqn(Lateq* ltq, ostream& docout)
820 {
821  ltq->println(docout);
822  //cerr << "Documentator : printDocEqn : "; ltq->println(cerr); cerr << endl;
823 }
824 
825 
826 /*****************************************************************************
827  Sub-function for <diagram> handling
828  *****************************************************************************/
829 
842 static void printDocDgm(const Tree expr, const char* svgTopDir, ostream& docout, int i)
843 {
845  Tree docdgm = evaldocexpr(expr, gExpandedDefList);
846  if (gErrorCount > 0) {
847  cerr << "Total of " << gErrorCount << " errors during evaluation of : diagram docdgm = " << boxpp(docdgm) << ";\n";
848  exit(1);
849  }
850 
855  char dgmid[MAXIDCHARS+1];
856  sprintf(dgmid, "%02d", i);
857  string thisdgmdir = subst("$0/svg-$1", svgTopDir, dgmid);
858  //cerr << "Documentator : printDocDgm : drawSchema in '" << gCurrentDir << "/" << thisdgmdir << "'" << endl;
859 
860  drawSchema( docdgm, thisdgmdir.c_str(), "svg" );
861 
863  char temp[1024];
864  const string dgmfilename = legalFileName(docdgm, 1024, temp);
865  //docout << "figure \\ref{figure" << i << "}";
866  docout << "\\begin{figure}[ht!]" << endl;
867  docout << "\t\\centering" << endl;
868  docout << "\t\\includegraphics[width=\\textwidth]{" << subst("../svg/svg-$0/", dgmid) << dgmfilename << "}" << endl;
869  docout << "\t\\caption{" << gDocMathStringMap["dgmcaption"] << " \\texttt{" << dgmfilename << "}}" << endl;
870  docout << "\t\\label{figure" << i << "}" << endl;
871  docout << "\\end{figure}" << endl << endl;
872 
874  gDocNoticeFlagMap["nameconflicts"] = true;
875  gDocNoticeFlagMap["svgdir"] = true;
876 }
877 
878 
879 
880 /*****************************************************************************
881  Other sub-functions
882  *****************************************************************************/
883 
884 
891 vector<string>& docCodeSlicer(const string& faustfile, vector<string>& codeSlices)
892 {
893  string s;
894  ifstream src;
895  src.open(faustfile.c_str(), ifstream::in);
896  string tmp = "";
897 
898  bool isInsideDoc = false;
899 
900  if (faustfile != "" && src.good()) {
901  while(getline(src, s)) {
902  size_t foundopendoc = s.find("<mdoc>");
903 
904  if (foundopendoc != string::npos) {
905  if (isInsideDoc == false) {
906  if (! tmp.empty() ) {
907  codeSlices.push_back(tmp); }
908  tmp = "";
909  }
910  isInsideDoc = true;
911  }
912 
913  if (isInsideDoc == false) {
914  tmp += s + '\n';
915  }
916 
917  size_t foundclosedoc = s.find("</mdoc>");
918  if (foundclosedoc != string::npos) isInsideDoc = false;
919  }
920  } else {
921  cerr << "ERROR : can't open faust source file " << faustfile << endl;
922  exit(1);
923  }
924  return codeSlices;
925 }
926 
927 
934 static void printdocCodeSlices(const string& code, ostream& docout)
935 {
936  if ( ! code.empty() ) {
937  docout << endl << "\\begin{lstlisting}[numbers=none, frame=none, basicstyle=\\small\\ttfamily, backgroundcolor=\\color{yobg}]" << endl;
938  docout << code << endl;
939  docout << "\\end{lstlisting}" << endl << endl;
940  }
941 }
942 
943 
949 static bool doesFileBeginWithCode(const string& faustfile)
950 {
951  string s;
952  ifstream src;
953  src.open(faustfile.c_str(), ifstream::in);
954 
955  if (faustfile != "" && src.good()) {
956  getline(src, s);
957  size_t foundopendoc = s.find("<mdoc>");
958  if(int(foundopendoc)==0) {
959  return false;
960  } else {
961  return true;
962  }
963  } else {
964  cerr << "ERROR : can't open faust source file " << faustfile << endl;
965  exit(1);
966  }
967 }
968 
969 
970 
971 //------------------------ dealing with files -------------------------
972 
973 
977 static istream* openArchFile (const string& filename)
978 {
979  istream* file;
980  getCurrentDir(); // Save the current directory.
981  //cerr << "Documentator : openArchFile : Opening input file '" << filename << "'" << endl;
982  if ( (file = open_arch_stream(filename.c_str())) ) {
983  //cerr << "Documentator : openArchFile : Opening '" << filename << "'" << endl;
984  } else {
985  cerr << "ERROR : can't open architecture file " << filename << endl;
986  exit(1);
987  }
988  cholddir(); // Return to current directory.
989  return file;
990 }
991 
992 
999 static char* legalFileName(const Tree t, int n, char* dst)
1000 {
1001  Tree id;
1002  int i=0;
1003  if (getDefNameProperty(t, id)) {
1004  const char* src = tree2str(id);
1005  for (i=0; isalnum(src[i]) && i<16; i++) {
1006  dst[i] = src[i];
1007  }
1008  }
1009  dst[i] = 0;
1010  if (strcmp(dst, "process") != 0) {
1011  // if it is not process add the hex address to make the name unique
1012  snprintf(&dst[i], n-i, "-%p", t);
1013  }
1014  return dst;
1015 }
1016 
1021 static string calcNumberedName(const char* base, int i)
1022 {
1023  char nb[MAXIDCHARS+1];
1024  sprintf(nb, "%03d", i);
1025  return subst("$0$1", base, nb);
1026 }
1027 
1032 static string rmExternalDoubleQuotes(const string& s)
1033 {
1034  size_t i = s.find_first_not_of("\"");
1035  size_t j = s.find_last_not_of("\"");
1036 
1037  if ( (i != string::npos) & (j != string::npos) ) {
1038  return s.substr(i, 1+j-i);
1039  } else {
1040  return "";
1041  }
1042 }
1043 
1044 
1051 static void copyFaustSources(const char* projname, const vector<string>& pathnames)
1052 {
1053  string srcdir = subst("$0/src", projname);
1054  //cerr << "Documentator : copyFaustSources : Creating directory '" << srcdir << "'" << endl;
1055  makedir(srcdir.c_str()); // create a directory.
1056 
1057  for (unsigned int i=0; i< pathnames.size(); i++) {
1058  ifstream src;
1059  ofstream dst;
1060  string faustfile = pathnames[i];
1061  string copy = subst("$0/$1", srcdir, filebasename(faustfile.c_str()));
1062  //cerr << "Documentator : copyFaustSources : Opening input file '" << faustfile << "'" << endl;
1063  //cerr << "Documentator : copyFaustSources : Opening output file '" << copy << "'" << endl;
1064  src.open(faustfile.c_str(), ifstream::in);
1065  dst.open(copy.c_str(), ofstream::out);
1066  string s;
1067  while ( getline(src,s) ) dst << s << endl;
1068  }
1069 }
1070 
1071 
1072 //------------------------ date managment -------------------------
1073 
1074 
1075 static void initCompilationDate()
1076 {
1077  time_t now;
1078 
1079  time(&now);
1080  gCompilationDate = *localtime(&now);
1081 }
1082 
1083 static struct tm* getCompilationDate()
1084 {
1086  return &gCompilationDate;
1087 }
1088 
bool getDefNameProperty(Tree t, Tree &id)
Indicates the identifier (if any) the expression was a definition of.
Definition: names.cpp:85
static char * legalFileName(const Tree t, int n, char *dst)
Transform the definition name property of tree into a legal file name.
Definition: doc.cpp:999
static void printlatexheader(istream &latexheader, const string &faustversion, ostream &docout)
Print a static LaTeX header.
Definition: doc.cpp:283
static string calcDocEqnInitial(const string s)
Calculate an appropriate nickname for equations, from previous names.
Definition: doc.cpp:783
static int cholddir()
Switch back to the previously stored current directory.
Definition: doc_lang.cpp:242
Tree docMtd(Tree x)
Definition: doc.cpp:201
int mkchdir(string dirname)
Create a new directory in the current one to store the diagrams.
Definition: files.cpp:55
Tree reverse(Tree l)
Definition: list.cpp:240
static void prepareDocEqns(const vector< Tree > &docBoxes, vector< Lateq * > &docCompiledEqnsVector)
Caller function.
Definition: doc.cpp:515
static string calcNumberedName(const char *base, int i)
Simply concat a string with a number in a "%03d" format.
Definition: doc.cpp:1021
Class Node = (type x (int + double + Sym + void*))
Definition: node.hh:75
#define MAXIDCHARS
max numbers (characters) to represent ids (e.g. for directories).
Definition: doc.cpp:83
static void annotateSuperList(DocCompiler *DC, Tree superEqList)
step 8. Annotate superlist.
Definition: doc.cpp:732
static void mapCompileDocEqnSigs(const vector< Tree > &eqSigs, const vector< int > &eqInputs, const vector< int > &eqOutputs, DocCompiler *DC, vector< Lateq * > &docCompiledEqnsVector)
step 10. Compile equations.
Definition: doc.cpp:755
Definition: doc.cpp:117
void drawSchema(Tree bd, const char *projname, const char *dev)
The entry point to generate from a block diagram as a set of svg files stored in the directory "
Definition: drawschema.cpp:161
static void mapSetSigNickname(const vector< string > &eqNicknames, const vector< int > &eqInputs, const vector< Tree > &eqSigs)
step 6. Set signals nicknames.
Definition: doc.cpp:692
Tree deBruijn2Sym(Tree t)
Tree cons(Tree a, Tree b)
Definition: list.hh:124
static void collectDocEqns(const vector< Tree > &docBoxes, vector< Tree > &eqBoxes)
step 0. Feed a vector.
Definition: doc.cpp:544
Tree evaldocexpr(Tree docexpr, Tree eqlist)
Definition: eval.cpp:114
map< string, bool > gDocNoticeFlagMap
gDocNoticeFlagMap is public to let others turn to "true" flags that one want to print.
Definition: doc_notice.cpp:36
static void printdoccontent(const char *svgTopDir, const vector< Tree > &docVector, const string &faustversion, ostream &docout)
Main documentator loop.
Definition: doc.cpp:436
Definition: doc.cpp:117
static struct tm * getCompilationDate()
Definition: doc.cpp:1083
bool gLstDistributedSwitch
mdoc listing management.
Definition: doc.cpp:115
A CTree = (Node x [CTree]) is a Node associated with a list of subtrees called branches.
Definition: tree.hh:109
bool gLstMdocTagsSwitch
mdoc listing management.
Definition: doc.cpp:114
ifstream * open_arch_stream(const char *filename)
Try to open an architecture file searching in various directories.
Definition: enrobage.cpp:220
static void copyFaustSources(const char *projname, const vector< string > &pathnames)
Copy all Faust source files into an 'src' subdirectory.
Definition: doc.cpp:1051
string gFaustSuperSuperDirectory
Definition: main.cpp:101
Definition: lateq.hh:56
Tree simplify(Tree sig)
Definition: simplify.cpp:76
Tree hd(Tree l)
Definition: list.hh:133
Tree gExpandedDefList
Definition: main.cpp:108
Tree docTableConvertion(Tree sig)
Definition: simplify.cpp:317
const Node & node() const
return the content of the tree
Definition: tree.hh:143
bool isDocDgm(Tree t, Tree &x)
Definition: doc.cpp:190
Tree docTxt(const char *name)
Definition: doc.cpp:171
static istream * openArchFile(const string &filename)
Open architecture file.
Definition: doc.cpp:977
Lateq * compileLateq(Tree L, Lateq *compiledEqn)
map< string, string > gDocMathStringMap
Definition: lateq.cpp:51
bool isDocNtc(Tree t)
Definition: doc.cpp:194
static void printDocEqn(Lateq *ltq, ostream &docout)
Print doc equations, following the Lateq::println method.
Definition: doc.cpp:819
Interface of the block diagram evaluator.
Sym DOCNTC
Definition: doc.cpp:192
int makedir(string dirname)
Definition: files.cpp:72
bool gStripDocSwitch
Definition: main.cpp:124
bool isDocTxt(Tree t)
Definition: doc.cpp:172
Tree docEqn(Tree x)
Definition: doc.cpp:185
Sym DOCEQN
Definition: doc.cpp:184
string gDocName
Contains the filename for out documentation.
Definition: main.cpp:107
string gDocLang
Definition: doc.cpp:118
Tree annotate(Tree L0)
Definition: doc_compile.cpp:88
Tree boxPropagateSig(Tree path, Tree box, const siglist &lsig)
Top level propagate a list of signals into a block diagram.
Definition: propagate.cpp:501
string gMasterName
Definition: main.cpp:106
vector< string > listSrcFiles()
Return a vector of pathnames representing the list of all the source files that have been required to...
static void initCompilationDate()
Definition: doc.cpp:1075
Tree docLst()
Definition: doc.cpp:197
string subst(const string &model, const vector< string > &args)
Text substitution.
Definition: Text.cpp:47
bool gDetailsSwitch
Definition: main.cpp:114
bool isList(Tree l)
Definition: list.hh:138
vector< Tree > gDocVector
Contains parsed trees: DOCTXT, DOCEQN, DOCDGM.
Definition: doc.cpp:109
const char * filebasename(const char *name)
returns a pointer on the basename part of name
Definition: enrobage.cpp:544
static void mapPrepareEqSig(const vector< Tree > &evalEqBoxes, vector< int > &eqInputs, vector< int > &eqOutputs, vector< Tree > &eqSigs)
step 4&5. Propagate and prepare signals.
Definition: doc.cpp:658
static void getCurrentDir()
Get current directory and store it in gCurrentDir.
Definition: doc_lang.cpp:256
map< Tree, set< Tree > > gMetaDataSet
Definition: main.cpp:91
bool isSym(const Node &n)
Definition: node.hh:199
static void getBoxInputsAndOutputs(const Tree t, int &numInputs, int &numOutputs)
Just get the number of inputs and the number of outputs of a box.
Definition: doc.cpp:803
#define doc
Definition: faustlexer.cpp:806
static void printlatexfooter(ostream &docout)
Print the static LaTeX footer.
Definition: doc.cpp:389
void println(ostream &docout)
Top-level method to print a whole set of compiled LaTeX formulas.
Definition: lateq.cpp:83
int gErrorCount
Definition: errormsg.cpp:31
siglist makeSigInputList(int n)
Fabrique une liste de n entrées.
Definition: propagate.cpp:96
static void collectEqSigs(const vector< Tree > &eqSigs, Tree &superEqList)
step 7. Collect all signals in a superlist.
Definition: doc.cpp:711
const char * name(Symbol *sym)
Returns the name of a symbol.
Definition: symbol.hh:98
static const string gLatexheaderfilename
Definition: doc.cpp:107
bool isDocMtd(Tree t, Tree &x)
Definition: doc.cpp:202
static void printfaustlistings(ostream &docout)
Print listings of each Faust code ".dsp" files, calling the 'printfaustlisting' function.
Definition: doc.cpp:331
vector< string > & docCodeSlicer(const string &faustfile, vector< string > &codeSlices)
Slice faust code between "mdoc" sections.
Definition: doc.cpp:891
Definition: doc.cpp:117
void loadTranslationFile(const string &lang)
Definition: doc_lang.cpp:76
Compile a list of FAUST signals into a list of LaTeX formulas.
Definition: doc_compile.hh:48
Tree tree(const Node &n)
Definition: tree.hh:186
string gFaustSuperDirectory
Definition: main.cpp:102
bool isDocEqn(Tree t, Tree &x)
Definition: doc.cpp:186
Tree docNtc()
Definition: doc.cpp:193
static void calcEqnsNicknames(const vector< string > &eqNames, vector< string > &eqNicknames)
step 3. Calculate nicknames.
Definition: doc.cpp:618
static void mapGetEqName(const vector< Tree > &evalEqBoxes, vector< string > &eqNames)
step 2. Get boxes name.
Definition: doc.cpp:588
Symbols are unique objects with a name stored in a hash table.
Definition: symbol.hh:53
Sym DOCDGM
Definition: doc.cpp:188
SourceReader gReader
Definition: main.cpp:89
bool isTree(const Tree &t, const Node &n)
Definition: tree.cpp:305
Definition: ppbox.hh:58
static string rmExternalDoubleQuotes(const string &s)
Remove the leading and trailing double quotes of a string (but not those in the middle of the string)...
Definition: doc.cpp:1032
static void printdocCodeSlices(const string &code, ostream &docout)
Print faust code inside a listing environment.
Definition: doc.cpp:934
Tree docDgm(Tree x)
Definition: doc.cpp:189
static const char * gDocDevSuffix
".tex" (or .??? - used to choose output device).
Definition: doc.cpp:106
string gMasterDocument
Definition: main.cpp:104
Tree nil
Definition: list.cpp:116
map< string, string > gDocMetadatasStringMap
Symbol * symbol(const char *str)
Returns (and creates if new) the symbol of name str.
Definition: symbol.hh:95
Sym DOCTXT
Definition: doc.cpp:170
static void printfaustlisting(string &path, ostream &docout)
Print a listing of the Faust code, in a LaTeX "listing" environment.
Definition: doc.cpp:351
string gFaustDirectory
Definition: main.cpp:103
bool isDocLst(Tree t)
Definition: doc.cpp:198
static void printDocMetadata(const Tree expr, ostream &docout)
Print a metadata set.
Definition: doc.cpp:311
Interface for names management.
void printDocNotice(const string &faustversion, ostream &docout)
Print the content of the notice (a string map), as LaTeX items inside an itemize environment.
Definition: doc_notice.cpp:66
static struct tm gCompilationDate
Definition: doc.cpp:111
static void mapEvalDocEqn(const vector< Tree > &eqBoxes, const Tree &env, vector< Tree > &evalEqBoxes)
step 1. Evaluate boxes.
Definition: doc.cpp:570
static void printDocDgm(const Tree expr, const char *svgTopDir, ostream &docout, int i)
Doc diagrams handling.
Definition: doc.cpp:842
static void printfaustdocstamp(const string &faustversion, ostream &docout)
Print a "doc stamp" in the LaTeX document :
Definition: doc.cpp:404
static bool doesFileBeginWithCode(const string &faustfile)
Test whether a file does begin with some faust code or not.
Definition: doc.cpp:949
void printDoc(const char *projname, const char *docdev, const char *faustversion)
The entry point to generate faust doc files.
Definition: doc.cpp:224
Tree tl(Tree l)
Definition: list.hh:134
Sym DOCLST
Definition: doc.cpp:196
const char * tree2str(Tree t)
if t has a node of type symbol, return its name otherwise error
Definition: tree.cpp:278
Tree branch(int i) const
return the ith branch (subtree) of a tree
Definition: tree.hh:145
void declareAutoDoc()
Declare an automatic documentation.
Definition: doc_autodoc.cpp:61
Sym DOCMTD
Definition: doc.cpp:200
bool getBoxType(Tree box, int *inum, int *onum)
Return the type (number of inputs and outputs) of a box or false if undefined.
Definition: boxtype.cpp:63
bool gLstDependenciesSwitch
mdoc listing management.
Definition: doc.cpp:113