Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
filter.cxx
Go to the documentation of this file.
1// @(#)root/test:$name: $:$id: filter.cxx,v 1.0 exp $
2// Author: O.Couet
3
4/// The ROOT doxygen filter implements ROOT's specific directives used to generate
5/// the ROOT reference guide.
6///
7/// ## In the ROOT classes
8///
9/// ### `Begin_Macro` and `End_Macro`
10/// The two tags where used the THtml version to generate images from ROOT code.
11/// The generated picture is inlined exactly at the place where the macro is
12/// defined. The Macro can be defined in two way:
13/// - by direct in-lining of the C++ code
14/// - by a reference to a C++ file
15/// The tag `Begin_Macro` can have the parameter `(source)`. The directive becomes:
16/// `Begin_Macro(source)`. This parameter allows to show the macro's code in addition.
17/// `Begin_Macro` also accept the image file type as option. "png" or "svg".
18/// "png" is the default value. For example: `Begin_Macro(source, svg)` will show
19/// the code of the macro and the image will be is svg format. The "width" keyword
20/// can be added to define the width of the picture in pixel: "width=400" will
21/// scale a picture to 400 pixel width. This allow to define large pictures which
22/// can then be scaled down to have a better definition.
23///
24/// ## In the ROOT tutorials
25///
26/// ROOT tutorials are also included in the ROOT documentation. The tutorials'
27/// macros headers should look like:
28///
29/// ~~~ {.cpp}
30/// \file
31/// \ingroup tutorial_hist
32/// \notebook
33/// \preview Getting Contours From TH2D.
34///
35/// #### Image produced by `.x hist102_TH2_contour_list.C`
36/// The contours values are drawn next to each contour.
37/// \macro_image
38///
39/// #### Output produced by `.x hist102_TH2_contour_list.C`
40/// It shows that 6 contours and 12 graphs were found.
41/// \macro_output
42///
43/// #### `hist102_TH2_contour_list.C`
44/// \macro_code
45///
46/// \authors Josh de Bever, Olivier Couet
47/// ~~~
48///
49/// This example shows that four new directives have been implemented:
50///
51/// 1. `\macro_image`
52/// The images produced by this macro are shown. A caption can be added to document
53/// the pictures: `\macro_image This is a picture`. When the option `(nobatch)`
54/// is passed, the macro is executed without the batch option.
55/// Some tutorials generate pictures (png or pdf) with `Print` or `SaveAs`.
56/// Such pictures can be displayed with `\macro_image (picture_name.png[.pdf])`
57/// When the option (tcanvas_js) is used the image is displayed as JavaScript.
58/// For ROOT 7 tutorials, when the option (rcanvas_js) is used the image is displayed as json file.
59///
60/// 2. `\macro_code`
61/// The macro code is shown. A caption can be added: `\macro_code This is code`
62///
63/// 3. `\macro_output`
64/// The output produced by this macro is shown. A caption can be added:
65/// `\macro_output This the macro output`
66///
67/// 4. `\notebook`
68/// To generate the corresponding jupyter notebook. In case the tutorial does
69/// not generate any graphics output, the option `-nodraw` should be added.
70///
71/// 5. `\preview`
72/// To display the first image generated by the tutorial as an icon in the list of tutorials.
73///
74/// Note that the doxygen directive `\authors` or `\author` must be the last one
75/// of the macro header.
76///
77/// ## In the Python doc files
78///
79/// The two tags `\pythondoc` and `\endpythondoc` should be used to start and finish
80/// python documentation.
81
82#include <unistd.h>
83#include <cstdio>
84#include <string>
85#include <cstring>
86#include <iostream>
87#include <fstream>
88#include <cstdlib>
89#include <cstdarg>
90#include <memory>
91
92using std::string;
93using std::ios_base;
94using std::unique_ptr;
95
96// Auxiliary functions
97void FilterClass();
98void FilterTutorial();
99void FilterPythonBox();
100void GetClassName();
101void CreateTutorialImage(bool);
102int NumberOfImages();
103string ImagesList(string&);
104void ExecuteMacro();
105void ExecuteCommand(string);
106void ReplaceAll(string&, const string&, const string&);
107string StringFormat(const string fmt_str, ...);
108bool EndsWith(string const &, string const &);
109bool BeginsWith(const string&, const string&);
110
111// Global variables.
112FILE *f; // Pointer to the file being parsed.
113char gLine[255]; // Current line in the current input file
114string gFileName; // Input file name
115string gLineString; // Current line (as a string) in the current input file
116string gClassName; // Current class name
117string gImageName; // Current image name
118string gMacroName; // Current macro name
119string gImageType; // Type of image used to produce pictures (png, svg ...)
120string gImageWidth; // Width of image
121string gCwd; // Current working directory
122string gOutDir; // Output directory
123string gSourceDir; // Source directory
124string gPythonExec; // Python executable
125string gOutputName; // File containing a macro std::out
126bool gHeader; // True if the input file is a header
127bool gSource; // True if the input file is a source file
128bool gPython; // True if the input file is a Python script.
129bool gImageGenerated;// True if the PNG image has been generated.
130bool gImageSource; // True the source of the current macro should be shown
131int gInMacro; // >0 if parsing a macro in a class documentation.
132int gImageID; // Image Identifier.
133int gMacroID; // Macro identifier in class documentation.
134
135
136////////////////////////////////////////////////////////////////////////////////
137/// Filter ROOT files for Doxygen.
138
139int main(int argc, char *argv[])
140{
141 // Initialisation
142 gFileName = argv[1];
143 gHeader = false;
144 gSource = false;
145 gPython = false;
146 gImageSource = false;
147 gImageGenerated= false;
148 gInMacro = 0;
149 gImageID = 0;
150 gMacroID = 0;
151 gOutputName = "stdout.dat";
152 gImageType = "png";
153 gImageWidth = "";
154 if (EndsWith(gFileName,".cxx")) gSource = true;
155 if (EndsWith(gFileName,".h")) gHeader = true;
156 if (EndsWith(gFileName,".py")) gPython = true;
157 GetClassName();
158
159 // Retrieve the current working directory
160 int last = gFileName.rfind("/");
161 gCwd = gFileName.substr(0,last);
162
163 // Retrieve the output directory
164 gOutDir = std::getenv("DOXYGEN_OUTPUT_DIRECTORY");
165 ReplaceAll(gOutDir,"\"","");
166
167 // Retrieve the source directory
168 gSourceDir = std::getenv("DOXYGEN_SOURCE_DIRECTORY");
169 ReplaceAll(gSourceDir,"\"","");
170
171 // Retrieve the python executable
172 gPythonExec = std::getenv("Python3_EXECUTABLE");
173 ReplaceAll(gPythonExec,"\"","");
174
175 // Open the input file name.
176 f = fopen(gFileName.c_str(),"r");
177 if (!f) return 1;
178
179 if (gFileName.find("tutorials") != string::npos) FilterTutorial();
180 else if (gFileName.find("pyzdoc") != string::npos) FilterPythonBox();
181 else FilterClass();
182}
183
184////////////////////////////////////////////////////////////////////////////////
185/// Filter ROOT python box for Doxygen.
186
188{
189 while (fgets(gLine,255,f)) {
191 if (gLineString.find("\\pythondoc") != string::npos) {
192 string class_name = gLineString;
193 ReplaceAll(class_name, " ", "");
194 ReplaceAll(class_name, "\\pythondoc", "");
195 ReplaceAll(class_name, "\n", "");
196 gLineString = StringFormat("/**\n\\class %s\n"
197 "\\brief \\parblock \\endparblock\n"
198 "\\htmlonly\n"
199 "<details open>\n"
200 "<summary style=\"font-size:20px; color: #425788;\">\n"
201 "<b>Python interface</b></summary>\n"
202 "<div class=\"pyrootbox\">\n"
203 "\\endhtmlonly\n"
204 "\\ingroup Pythonizations", class_name.c_str());
205 }
206 if (gLineString.find("\\endpythondoc") != string::npos)
207 ReplaceAll(gLineString, "\\endpythondoc", "\\htmlonly </div> </details> \\endhtmlonly\n*/");
208 printf("%s",gLineString.c_str());
209 }
210 fclose(f);
211}
212
213////////////////////////////////////////////////////////////////////////////////
214/// Filter ROOT class for Doxygen.
215
217{
218 // File for inline macros.
219 FILE *m = 0;
220
221 // File header.
222 if (gHeader) {
223 while (fgets(gLine,255,f)) {
225 printf("%s",gLineString.c_str());
226 }
227 fclose(f);
228 return;
229 }
230
231 // Source file.
232 if (gSource) {
233 size_t spos = 0;
234 while (fgets(gLine,255,f)) {
236
237 if (gInMacro && gLineString.find("End_Macro") != string::npos) {
238 gImageSource = false;
239 gInMacro = 0;
240 spos = 0;
241 if (m) {
242 fclose(m);
243 m = 0;
245 StringFormat("root -b -q \"makeimage.C+O(\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",true,false)\"",
246 StringFormat("%s_%3.3d.C", gClassName.c_str(), gMacroID).c_str(),
247 StringFormat("%s_%3.3d.%s", gClassName.c_str(), gImageID, gImageType.c_str()).c_str(),
248 gOutDir.c_str()));
249 ExecuteCommand(StringFormat("rm %s_%3.3d.C", gClassName.c_str(), gMacroID));
250 }
251 int ImageSize = 300;
252 FILE *f = fopen("ImagesSizes.dat", "r");
253 if (!f) return;
254 if (fscanf(f, "%d", &ImageSize) == 1) {
255 ReplaceAll(gImageWidth, "IMAGESIZE", StringFormat("%d", ImageSize));
256 ReplaceAll(gLineString, "End_Macro",
257 StringFormat("\\image html pict1_%s_%3.3d.%s %s", gClassName.c_str(), gImageID,
258 gImageType.c_str(), gImageWidth.c_str()));
259 }
260 fclose(f);
261 remove("ImagesSizes.dat");
262 }
263
264 if (gInMacro) {
265 if (spos) gLineString = gLineString.substr(spos);
266 if (gInMacro == 1) {
267 if (EndsWith(gLineString,".C\n") || (gLineString.find(".C(") != string::npos)) {
268 ExecuteMacro();
269 gInMacro++;
270 } else {
271 gMacroID++;
272 m = fopen(StringFormat("%s_%3.3d.C", gClassName.c_str(), gMacroID).c_str(), "w");
273 if (m) fprintf(m,"%s",gLineString.c_str());
274 if (BeginsWith(gLineString,"{")) {
275 if (gImageSource) {
277 , StringFormat("\\include %s_%3.3d.C"
278 , gClassName.c_str()
279 , gMacroID));
280 } else {
281 gLineString = "\n";
282 }
283 }
284 gInMacro++;
285 }
286 } else {
287 if (m) fprintf(m,"%s",gLineString.c_str());
288 if (BeginsWith(gLineString,"}")) {
289 ReplaceAll(gLineString,"}","");
290 } else {
291 gLineString = "\n";
292 }
293 gInMacro++;
294 }
295 }
296
297 if (gLineString.find("Begin_Macro") != string::npos &&
298 gLineString.find("End_Macro") == string::npos) {
299 if (BeginsWith(gLineString, "///")) {
300 spos = gLineString.find_first_not_of(' ', 3);
301 }
302 if (gLineString.find("source") != string::npos) gImageSource = true;
303 if (gLineString.find("png") != string::npos) {
304 gImageType = "png";
305 } else if (gLineString.find("svg") != string::npos) {
306 gImageType = "svg";
307 } else {
308 gImageType = "png";
309 }
310 gImageWidth = "";
311 int wpos1 = gLineString.find("\"width=");
312 if (wpos1 != string::npos) {
313 int wpos2 = gLineString.find_first_of("\"", wpos1+1);
314 gImageWidth = gLineString.substr(wpos1+1, wpos2-wpos1-1);
315 } else {
316 gImageWidth = "width=IMAGESIZE";
317 }
318 gImageID++;
319 gInMacro++;
320 gLineString = "\n";
321 }
322
323 size_t l = gLineString.length();
324 size_t b = 0;
325 do {
326 size_t e = gLineString.find('\n', b);
327 if (e != string::npos) e++;
328 if (spos) printf("%-*s%s", (int)spos, "///",
329 gLineString.substr(b, e - b).c_str());
330 else printf("%s", gLineString.substr(b, e - b).c_str());
331 b = e;
332 } while (b < l);
333 }
334 fclose(f);
335 return;
336 }
337
338 // Output anything not header nor source
339 while (fgets(gLine,255,f)) {
341 printf("%s",gLineString.c_str());
342 }
343 fclose(f);
344}
345
346////////////////////////////////////////////////////////////////////////////////
347/// Create PNG tutorial image
348
349void CreateTutorialImage(bool nobatch) {
350 if (gPython) {
351 if (nobatch) {
352 ExecuteCommand(StringFormat("%s makeimage.py %s %s %s 0 1 0",
353 gPythonExec.c_str(),
354 gFileName.c_str(), gImageName.c_str(), gOutDir.c_str()));
355 } else {
356 ExecuteCommand(StringFormat("%s makeimage.py %s %s %s 0 1 1",
357 gPythonExec.c_str(),
358 gFileName.c_str(), gImageName.c_str(), gOutDir.c_str()));
359 }
360 } else {
361 if (nobatch) {
363 StringFormat("root -q \"makeimage.C+O(\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",false,false)\"",
364 gFileName.c_str(), gImageName.c_str(), gOutDir.c_str()));
365 } else {
367 StringFormat("root -b -q \"makeimage.C+O(\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",false,false)\"",
368 gFileName.c_str(), gImageName.c_str(), gOutDir.c_str()));
369 }
370 }
371 gImageGenerated = true;
372}
373
374////////////////////////////////////////////////////////////////////////////////
375/// Filter ROOT tutorials for Doxygen.
376
378{
379 // Use these to write out work that should be run in parallel after doxygen is done:
380 // This executes python <work>
381 std::ofstream worklist_py("tutorialWorklist_py", ios_base::app);
382 // This executes root <work>
383 std::ofstream worklist_root("tutorialWorklist_root", ios_base::app);
384
385 // File for inline macros.
386 FILE *m = 0;
387
388 int showTutSource = 0;
389 int incond = 0;
390
391 // Extract the macro name
392 int i1 = gFileName.rfind('/')+1;
393 int i2;
394 if (gPython) {
395 i2 = gFileName.rfind('y');
396 } else {
397 i2 = gFileName.rfind('C');
398 }
399 gImageGenerated = false;
400 gMacroName = gFileName.substr(i1,i2-i1+1);
401 gImageName = StringFormat("%s.%s", gMacroName.c_str(), gImageType.c_str()); // Image name
402 gOutputName = StringFormat("%s.out", gMacroName.c_str()); // output name
403 if (gPython) {
404 FILE *cn = fopen("CleanNamespaces.sh", "a");
405 string name = gMacroName;
406 ReplaceAll(name,".py","");
407 ReplaceAll(name,"_","__");
408 if (cn)
409 fprintf(cn,"./modifyNamespacesWebpage.sh %s\n",name.c_str());
410 fclose(cn);
411 }
412
413 // Parse the source and generate the image if needed
414 while (fgets(gLine,255,f)) {
416
417 // \macro_image found
418 if (gLineString.find("\\macro_image") != string::npos) {
419 bool nobatch = (gLineString.find("(nobatch)") != string::npos);
420 ReplaceAll(gLineString,"(nobatch)","");
421 bool tcanvas_js = false, rcanvas_js = false;
422 int tcanvas_aclic = 0;
423
424 if (gLineString.find("(tcanvas_js)") != string::npos) {
425 tcanvas_js = true;
426 tcanvas_aclic = 0;
427 ReplaceAll(gLineString,"(tcanvas_js)", "");
428 }
429
430 if (gLineString.find("(tcanvas_jsp)") != string::npos) {
431 tcanvas_js = true;
432 tcanvas_aclic = 1;
433 ReplaceAll(gLineString,"(tcanvas_jsp)", "");
434 }
435
436 if (gLineString.find("(rcanvas_js)") != string::npos) {
437 rcanvas_js = true;
438 ReplaceAll(gLineString,"(rcanvas_js)", "");
439 }
440
441 bool image_created_by_macro = (gLineString.find(".png)") != string::npos) ||
442 (gLineString.find(".svg)") != string::npos) ||
443 (gLineString.find(".pdf)") != string::npos);
444 if (image_created_by_macro) {
445 string image_name = gLineString;
446 ReplaceAll(image_name, " ", "");
447 ReplaceAll(image_name, "///\\macro_image(", "");
448 ReplaceAll(image_name, ")\n", "");
449 if (gPython) {
450 ExecuteCommand(StringFormat("%s %s", gPythonExec.c_str(), gFileName.c_str()));
451 } else {
452 ExecuteCommand(StringFormat("root -b -q %s", gFileName.c_str()));
453 }
454 ExecuteCommand(StringFormat("mv %s %s/html", image_name.c_str(), gOutDir.c_str()));
455 ReplaceAll(gLineString, "macro_image (", "image html ");
456 ReplaceAll(gLineString, ")", "");
457 } else if (tcanvas_js) {
458 string IN;
459 IN = gImageName;
460 int i = IN.find(".");
461 IN.erase(i,IN.length());
462 ExecuteCommand(StringFormat("root -b -q \"MakeTCanvasJS.C(\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",false,%d,%d)\"",
463 gFileName.c_str(), IN.c_str(), gOutDir.c_str(), gPython, tcanvas_aclic));
464 ReplaceAll(gLineString, "macro_image", StringFormat("htmlinclude %s.html",IN.c_str()));
465 } else if (rcanvas_js) {
466 string IN;
467 IN = gImageName;
468 int i = IN.find(".");
469 IN.erase(i,IN.length());
471 "root -b -q --web=batch \"MakeRCanvasJS.C+O(\\\"%s\\\",\\\"%s\\\",\\\"%s\\\",false,%d)\"",
472 gFileName.c_str(), IN.c_str(), gOutDir.c_str(), gPython));
473 ReplaceAll(gLineString, "macro_image", StringFormat("htmlinclude %s.html",IN.c_str()));
474 } else {
476 ReplaceAll(gLineString, "\\macro_image", ImagesList(gImageName));
477 remove(gOutputName.c_str());
478 }
479 }
480
481 // \macro_code found
482 if (gLineString.find("\\macro_code") != string::npos) {
483 showTutSource = 1;
484 m = fopen(StringFormat("%s/macros/%s",gOutDir.c_str(),gMacroName.c_str()).c_str(), "w");
485 ReplaceAll(gLineString, "\\macro_code", StringFormat("\\include %s",gMacroName.c_str()));
486 }
487
488 // \notebook found
489 if (gLineString.find("\\notebook") != string::npos) {
490 // Notebooks are generated in dedicated step:
491 worklist_py << "converttonotebook.py " << gFileName << " " << gOutDir << "/notebooks/" << std::endl;
492
493 if (gPython){
494 gLineString = "## ";
495 }
496 else{
497 gLineString = "/// ";
498 }
499 gLineString += StringFormat( "\\htmlonly <a href=\"https://nbviewer.jupyter.org/url/root.cern/doc/master/notebooks/%s.nbconvert.ipynb\" target=\"_blank\"><img src= notebook.gif alt=\"View in nbviewer\" style=\"height:1.5em\" ></a> <a href=\"https://cern.ch/swanserver/cgi-bin/go?projurl=https://root.cern/doc/master/notebooks/%s.nbconvert.ipynb\" target=\"_blank\"><img src=\"https://swanserver.web.cern.ch/swanserver/images/badge_swan_white_150.png\" alt=\"Open in SWAN\" style=\"height:1.5em\" ></a> <br/>\\endhtmlonly \n", gMacroName.c_str() , gMacroName.c_str());
500 }
501
502 // \preview found
503 if (gLineString.find("\\preview") != string::npos) {
505 string name = gMacroName;
506 int width = 150;
507 ReplaceAll(name,"_","__");
508 ReplaceAll(name,".C","_8C.html");
509 ReplaceAll(gLineString, "\\preview", StringFormat("\\htmlonly <a href=\"%s\"><img src=\"pict1_%s.png\" style=\"float: left; margin-right: 10px;\" width=\"%d\"/></a>\\endhtmlonly",name.c_str(),gMacroName.c_str(),width));
510 }
511
512 // \macro_output found
513 if (gLineString.find("\\macro_output") != string::npos) {
514 remove(gOutputName.c_str());
515 if (!gPython) ExecuteCommand(StringFormat("root -b -q %s", gFileName.c_str()).c_str());
516 else ExecuteCommand(StringFormat("%s %s", gPythonExec.c_str(), gFileName.c_str()).c_str());
517 ExecuteCommand(StringFormat("sed -i '/Processing/d' %s", gOutputName.c_str()).c_str());
518 rename(gOutputName.c_str(), StringFormat("%s/macros/%s",gOutDir.c_str(), gOutputName.c_str()).c_str());
519 ReplaceAll(gLineString, "\\macro_output", StringFormat("\\include %s",gOutputName.c_str()));
520 }
521
522 // \author is the last comment line.
523 if (gLineString.find("\\author") != string::npos) {
524 if (gPython) printf("%s",StringFormat("%s \n## \\cond \n",gLineString.c_str()).c_str());
525 else printf("%s",StringFormat("%s \n/// \\cond \n",gLineString.c_str()).c_str());
526 if (showTutSource == 1) {
527 showTutSource = 2;
528 m = fopen(StringFormat("%s/macros/%s",gOutDir.c_str(),gMacroName.c_str()).c_str(), "w");
529 }
530 incond = 1;
531 } else {
532 printf("%s",gLineString.c_str());
533 if (m && showTutSource == 2) fprintf(m,"%s",gLineString.c_str());
534 }
535 }
536
537 if (incond) {
538 if (gPython) printf("## \\endcond \n");
539 else printf("/// \\endcond \n");
540 }
541
542 if (m) {
543 fclose(m);
544 }
545}
546
547////////////////////////////////////////////////////////////////////////////////
548/// Retrieve the class name.
549
551{
552 int i1 = 0;
553 int i2 = 0;
554
555 // File header.
556 if (gHeader) {
557 i1 = gFileName.find_last_of("/")+1;
558 i2 = gFileName.find(".h")-1;
559 gClassName = gFileName.substr(i1,i2-i1+1);
560 }
561
562 // Source file.
563 if (gSource) {
564 i1 = gFileName.find_last_of("/")+1;
565 i2 = gFileName.find(".cxx")-1;
566 gClassName = gFileName.substr(i1,i2-i1+1);
567 }
568
569 return;
570}
571
572////////////////////////////////////////////////////////////////////////////////
573/// Execute the macro in gLineString and produce the corresponding picture.
574
576{
577 // Name of the next Image to be generated
578 gImageName = StringFormat("%s_%3.3d.%s", gClassName.c_str(), gImageID, gImageType.c_str());
579
580 // Retrieve the macro to be executed.
581 if (gLineString.find("../../..") != string::npos) {
582 ReplaceAll(gLineString,"../../..", gSourceDir.c_str());
583 } else {
584 gLineString.insert(0, StringFormat("%s/../doc/macros/",gCwd.c_str()));
585 }
586 int i1 = gLineString.rfind('/')+1;
587 int i2 = gLineString.rfind('C');
588 gMacroName = gLineString.substr(i1,i2-i1+1);
589
590 // Build the ROOT command to be executed.
591 gLineString.insert(0, StringFormat("root -b -q \"makeimage.C+O(\\\""));
592 size_t l = gLineString.length();
593 gLineString.replace(l-1,1,StringFormat("\\\",\\\"%s\\\",\\\"%s\\\",true,false)\"", gImageName.c_str(), gOutDir.c_str()));
594
595 // Execute the macro
597
598 // Inline the directives to show the code
599 if (gImageSource) gLineString = StringFormat("\\include %s\n", gMacroName.c_str());
600 else gLineString = "";
601}
602
603////////////////////////////////////////////////////////////////////////////////
604/// Execute a command making sure stdout will not go in the doxygen file.
605
606void ExecuteCommand(string command)
607{
608 int o = dup(fileno(stdout));
609 if (freopen(gOutputName.c_str(), "a", stdout) != nullptr) {
610 int i = system(command.c_str());
611 dup2(o, fileno(stdout));
612 close(o);
613 }
614}
615
616////////////////////////////////////////////////////////////////////////////////
617/// Get the number of images in NumberOfImages.dat after makeimage.C is executed.
618
620{
621 int ImageNum;
622 FILE *f = fopen("NumberOfImages.dat", "r");
623 if (!f) return 0;
624 if (fscanf(f, "%d", &ImageNum) != 1)
625 ImageNum = 0;
626 fclose(f);
627 remove("NumberOfImages.dat");
628 return ImageNum;
629}
630
631////////////////////////////////////////////////////////////////////////////////
632/// Replace all instances of a string with another string.
633
634void ReplaceAll(string& str, const string& from, const string& to) {
635 if (from.empty()) return;
636 string wsRet;
637 wsRet.reserve(str.length());
638 size_t start_pos = 0, pos;
639 while ((pos = str.find(from, start_pos)) != string::npos) {
640 wsRet += str.substr(start_pos, pos - start_pos);
641 wsRet += to;
642 pos += from.length();
643 start_pos = pos;
644 }
645 wsRet += str.substr(start_pos);
646 str.swap(wsRet);
647}
648
649////////////////////////////////////////////////////////////////////////////////
650/// std::string formatting like sprintf.
651
652string StringFormat(const string fmt_str, ...) {
653 int final_n, n = ((int)fmt_str.size()) * 2; /* Reserve two times as much as the length of the fmt_str */
654 string str;
655 unique_ptr<char[]> formatted;
656 va_list ap;
657 while (1) {
658 formatted.reset(new char[n]); /* Wrap the plain char array into the unique_ptr */
659 strcpy(&formatted[0], fmt_str.c_str());
660 va_start(ap, fmt_str);
661 final_n = vsnprintf(&formatted[0], n, fmt_str.c_str(), ap);
662 va_end(ap);
663 if (final_n < 0 || final_n >= n) n += abs(final_n - n + 1);
664 else break;
665 }
666 return string(formatted.get());
667}
668
669////////////////////////////////////////////////////////////////////////////////
670/// Return the image list after a tutorial macro execution.
671
672string ImagesList(string& name) {
673
674 int N = NumberOfImages();
675
676 // evaluate the size of the output string
677 char evalstring[300];
678 snprintf(&evalstring[0], 300, " \n/// \\image html pict%d_%s width=%d", N, name.c_str(), 10000);
679 int evallen = (int)strlen(evalstring);
680
681 // allocate the output string
682 int vallen = sizeof(char) * evallen * N;
683 char *val = (char *)malloc(vallen);
684 int len = 0;
685
686 int ImageSize = 300;
687 FILE *f = fopen("ImagesSizes.dat", "r");
688 if (!f) return "";
689
690 for (int i = 1; i <= N; i++){
691 if (fscanf(f, "%d", &ImageSize) == 1) {
692 if (i > 1) {
693 if (gPython)
694 snprintf(&val[len], vallen, " \n## \\image html pict%d_%s width=%d", i, name.c_str(), ImageSize);
695 else
696 snprintf(&val[len], vallen, " \n/// \\image html pict%d_%s width=%d", i, name.c_str(), ImageSize);
697 } else {
698 snprintf(&val[len], vallen, "\\image html pict%d_%s width=%d", i, name.c_str(), ImageSize);
699 }
700 len = (int)strlen(val);
701 }
702 }
703
704 fclose(f);
705 remove("ImagesSizes.dat");
706
707 return (string)val;
708}
709
710////////////////////////////////////////////////////////////////////////////////
711/// Find if a string ends with another string.
712
713bool EndsWith(string const &fullString, string const &ending) {
714 if (fullString.length() >= ending.length()) {
715 return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
716 } else {
717 return false;
718 }
719}
720
721////////////////////////////////////////////////////////////////////////////////
722/// Find if a string begins with another string.
723
724bool BeginsWith(const string& haystack, const string& needle) {
725 return needle.length() <= haystack.length() && equal(needle.begin(), needle.end(), haystack.begin());
726}
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define e(i)
Definition RSha256.hxx:103
#define N
char name[80]
Definition TGX11.cxx:148
#define snprintf
Definition civetweb.c:1579
#define malloc
Definition civetweb.c:1575
void CreateTutorialImage(bool)
Create PNG tutorial image.
Definition filter.cxx:349
bool EndsWith(string const &, string const &)
Find if a string ends with another string.
Definition filter.cxx:713
string gImageWidth
Definition filter.cxx:120
bool gHeader
Definition filter.cxx:126
void FilterPythonBox()
Filter ROOT python box for Doxygen.
Definition filter.cxx:187
string gOutputName
Definition filter.cxx:125
string gCwd
Definition filter.cxx:121
string gImageName
Definition filter.cxx:117
char gLine[255]
Definition filter.cxx:113
bool gImageGenerated
Definition filter.cxx:129
void ExecuteCommand(string)
Execute a command making sure stdout will not go in the doxygen file.
Definition filter.cxx:606
string ImagesList(string &)
Return the image list after a tutorial macro execution.
Definition filter.cxx:672
bool gImageSource
Definition filter.cxx:130
int NumberOfImages()
Get the number of images in NumberOfImages.dat after makeimage.C is executed.
Definition filter.cxx:619
void ReplaceAll(string &, const string &, const string &)
Replace all instances of a string with another string.
Definition filter.cxx:634
void ExecuteMacro()
Execute the macro in gLineString and produce the corresponding picture.
Definition filter.cxx:575
string gOutDir
Definition filter.cxx:122
void GetClassName()
Retrieve the class name.
Definition filter.cxx:550
string gSourceDir
Definition filter.cxx:123
string gFileName
Definition filter.cxx:114
string gClassName
Definition filter.cxx:116
int gInMacro
Definition filter.cxx:131
string gPythonExec
Definition filter.cxx:124
string gImageType
Definition filter.cxx:119
void FilterTutorial()
Filter ROOT tutorials for Doxygen.
Definition filter.cxx:377
int gMacroID
Definition filter.cxx:133
int gImageID
Definition filter.cxx:132
string gMacroName
Definition filter.cxx:118
bool gSource
Definition filter.cxx:127
string StringFormat(const string fmt_str,...)
std::string formatting like sprintf.
Definition filter.cxx:652
void FilterClass()
Filter ROOT class for Doxygen.
Definition filter.cxx:216
bool gPython
Definition filter.cxx:128
string gLineString
Definition filter.cxx:115
bool BeginsWith(const string &, const string &)
Find if a string begins with another string.
Definition filter.cxx:724
int main()
printf("Client 0: bytes recv = %d, bytes sent = %d\n", s0->GetBytesRecv(), s0->GetBytesSent())
const Int_t n
Definition legend1.C:16
int width
Definition main.c:107
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4