0028950: Generation of draw_test_harness and upgrade pdf files is crashed
[occt.git] / adm / gendoc.tcl
1 # =======================================================================
2 # Created on: 2014-03-21
3 # Created by: OMY
4 # Copyright (c) 1996-1999 Matra Datavision
5 # Copyright (c) 1999-2014 OPEN CASCADE SAS
6 #
7 # This file is part of Open CASCADE Technology software library.
8 #
9 # This library is free software; you can redistribute it and/or modify it under
10 # the terms of the GNU Lesser General Public License version 2.1 as published
11 # by the Free Software Foundation, with special exception defined in the file
12 # OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13 # distribution for complete text of the license and disclaimer of any warranty.
14 #
15 # Alternatively, this file may be used under the terms of Open CASCADE
16 # commercial license or contractual agreement.
17  
18 # =======================================================================
19 # This script defines command gendoc compiling OCCT documents 
20 # from *.md files to HTML pages
21 # =======================================================================
22
23 # load auxiliary tools
24 source [file join [file dirname [info script]] occaux.tcl]
25
26 # ======================================
27 #  Common functions
28 # ======================================
29
30 # Prints help message
31 proc OCCDoc_PrintHelpMessage {} {
32     puts "\nUsage: gendoc \[-h\] {-refman|-overview} \[-html|-pdf|-chm\] \[-m=<list of modules>|-ug=<list of docs>\] \[-v\] \[-s=<search_mode>\] \[-mathjax=<path>\]"
33     puts ""
34     puts "Options are:"
35     puts ""
36     puts "choice of documentation to be generated:"
37     puts "  -overview          : To generate Overview and User Guides"
38     puts "                       (cannot be used with -refman)"
39     puts "  -refman            : To generate class Reference Manual"
40     puts "                       (cannot be used with -overview)"
41     puts ""
42     puts "choice of output format:"
43     puts "  -html              : To generate HTML files"
44     puts "                       (default, cannot be used with -pdf or -chm)"
45     puts "  -pdf               : To generate PDF files"
46     puts "                       (cannot be used with -refman, -html, or -chm)"
47     puts "  -chm               : To generate CHM files"
48     puts "                       (cannot be used with -html or -pdf)"
49     puts ""
50     puts "additional options:"
51     puts "  -m=<modules_list>  : List of OCCT modules (separated with comma),"
52     puts "                       for generation of Reference Manual"
53     puts "  -ug=<docs_list>    : List of MarkDown documents (separated with comma),"
54     puts "                       to use for generation of Overview / User Guides"
55     puts "  -mathjax=<path>    : To use local or alternative copy of MathJax"
56     puts "  -s=<search_mode>   : Specifies the Search mode of HTML documents"
57     puts "                       Can be: none | local | server | external"
58     puts "  -h                 : Prints this help message"
59     puts "  -v                 : Enables more verbose output"
60 }
61
62 # A command for User Documentation compilation
63 proc gendoc {args} {
64
65   # Parameters
66   set DOC_TYPE                  "REFMAN"
67   set GEN_MODE                  "HTML_ONLY"
68   set DOCFILES                  {}
69   set MODULES                   {}
70   set DOCLABEL                  ""
71   set VERB_MODE                 "NO"
72   set SEARCH_MODE               "none"
73   set MATHJAX_LOCATION          "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1"
74   set mathjax_js_name           "MathJax.js"
75   set DOCTYPE_COMBO_FLAG        0
76   set GENMODE_COMBO_FLAG        0
77   set GENERATE_PRODUCTS_REFMAN "NO"
78
79   global available_docfiles;   # The full list of md files for HTML or CHM generation
80   global available_pdf;        # The full list of md files for PDF generation
81   global tcl_platform
82   global args_names
83   global args_values
84   global env
85
86   # Load list of docfiles
87   if { [OCCDoc_LoadFilesList] != 0 } {
88     puts "Error: File FILES_HTML.txt or FILES_PDF.txt was not found on this computer.\nAborting..."
89     return -1
90   }
91
92   # Parse CL arguments
93   if {[OCCDoc_ParseArguments $args] == 1} {
94     return -1
95   }
96
97   # Print help message if no arguments provided
98   if {[llength $args_names] == 0} {
99     OCCDoc_PrintHelpMessage
100     return 0
101   }
102
103   foreach arg_n $args_names {
104     if {$arg_n == "h"} {
105       OCCDoc_PrintHelpMessage
106       return 0
107     } elseif {$arg_n == "html"} {
108       if { ([ lsearch $args_names "refman" ]   == -1) &&
109            ([ lsearch $args_names "overview" ] == -1) } {
110         puts "Warning: Please specify -refman or -overview argument."
111         return -1
112       }
113       if { [ lsearch $args_names "refman" ] != -1 } {
114         continue
115       }
116       if { $GENMODE_COMBO_FLAG != 1 } {
117         set GEN_MODE "HTML_ONLY"
118         set GENMODE_COMBO_FLAG 1
119       } else {
120         puts "Error: Options -html, -pdf and -chm can not be combined."
121         return -1
122       }
123     } elseif {$arg_n == "chm"} {
124       if { ([ lsearch $args_names "refman" ]   == -1) &&
125            ([ lsearch $args_names "overview" ] == -1) } {
126         puts "Warning: Please specify -refman or -overview argument."
127         return -1
128       }
129       if { [ lsearch $args_names "refman" ] != -1 } {
130         continue
131       }
132       if { $GENMODE_COMBO_FLAG != 1 } { 
133         set GEN_MODE "CHM_ONLY"
134         set GENMODE_COMBO_FLAG 1
135       } else {
136         puts "Error: Options -html, -pdf and -chm cannot be combined."
137         return -1
138       }
139     } elseif {$arg_n == "pdf"} {
140       if { ([ lsearch $args_names "refman" ]   == -1) &&
141            ([ lsearch $args_names "overview" ] == -1) } {
142         puts "Warning: Please specify -refman or -overview argument."
143         return -1
144       }
145       if { [ lsearch $args_names "refman" ] != -1 } {
146         continue
147       }
148       if { $GENMODE_COMBO_FLAG != 1 } { 
149         set GEN_MODE "PDF_ONLY"
150         set GENMODE_COMBO_FLAG 1
151       } else {
152         puts "Error: Options -html, -pdf and -chm cannot be combined."
153         return -1
154       }
155     } elseif {$arg_n == "overview"} {
156       if { $DOCTYPE_COMBO_FLAG != 1 } {
157         set DOC_TYPE "OVERVIEW"
158         set DOCTYPE_COMBO_FLAG 1
159       } else {
160         puts "Error: Options -refman and -overview cannot be combined."
161         return -1
162       }
163
164       # Print ignored options
165       if { [ lsearch $args_names "m" ] != -1 } {
166         puts "\nInfo: The following options will be ignored: \n"
167         puts "  * -m"
168       }
169       puts ""
170     } elseif {$arg_n == "refman"} {
171       if { $DOCTYPE_COMBO_FLAG != 1 } { 
172         set DOC_TYPE "REFMAN"
173         set DOCTYPE_COMBO_FLAG 1
174         if { [file exists [OCCDoc_GetProdRootDir]/src/VAS/Products.tcl] } {
175           set GENERATE_PRODUCTS_REFMAN "YES"
176         }
177       } else {
178         puts "Error: Options -refman and -overview cannot be combined."
179         return -1
180       }
181       # Print ignored options
182       if { ([ lsearch $args_names "pdf" ]     != -1) || 
183            ([ lsearch $args_names "chm" ]     != -1) || 
184            ([ lsearch $args_names "ug" ]      != -1) } {
185         puts "\nInfo: The following options will be ignored: \n"
186         if { [ lsearch $args_names "pdf" ] != -1 } {
187           puts "  * -pdf"
188         }
189         if { [ lsearch $args_names "chm" ] != -1 } {
190           puts "  * -chm"
191         }
192         if { [ lsearch $args_names "ug" ] != -1 } {
193           puts "  * -ug"
194         }
195         puts ""
196       }
197       
198     } elseif {$arg_n == "v"} {
199       set VERB_MODE "YES"
200     } elseif {$arg_n == "ug"} {
201       if { ([ lsearch $args_names "refman" ]   != -1) } {
202         continue
203       }
204       if {$args_values(ug) != "NULL"} {
205         set DOCFILES $args_values(ug)
206       } else {
207         puts "Error in argument ug."
208         return -1
209       }
210       # Check if all chosen docfiles are correct
211       foreach docfile $DOCFILES {
212         if { [ lsearch $args_names "pdf" ] == -1 } {
213           # Check to generate HTMLs
214           if { [lsearch $available_docfiles $docfile] == -1 } {
215             puts "Error: File \"$docfile\" is not presented in the list of available docfiles."
216             puts "       Please specify the correct docfile name."
217             return -1
218           } 
219         } else {
220           # Check to generate PDFs
221           if { [lsearch $available_pdf $docfile] == -1 } {
222             puts "Error: File \"$docfile\" is not presented in the list of generic PDFs."
223             puts "       Please specify the correct pdf name."
224             return -1
225           }
226         }
227       }
228     } elseif {$arg_n == "m"} {
229       if { [ lsearch $args_names "overview" ] != -1 } {
230         continue
231       }
232       if {$args_values(m) != "NULL"} {
233         set MODULES $args_values(m)
234       } else {
235         puts "Error in argument m."
236         return -1
237       }
238     } elseif {$arg_n == "s"} {
239       if { [ lsearch $args_names "pdf" ] != -1 } {
240         continue
241       }
242       if {$args_values(s) != "NULL"} {
243         set SEARCH_MODE $args_values(s)
244       } else {
245         puts "Error in argument s."
246         return -1
247       }
248     } elseif {$arg_n == "mathjax"} {
249       if { [ lsearch $args_names "pdf" ] != -1 } {
250         set possible_mathjax_loc $args_values(mathjax)
251         if {[file exist [file join $possible_mathjax_loc $mathjax_js_name]]} {
252           set MATHJAX_LOCATION $args_values(mathjax)
253           puts "$MATHJAX_LOCATION"
254         } else {
255           puts "Warning: $mathjax_js_name is not found in $possible_mathjax_loc."
256           puts "         MathJax will be used from $MATHJAX_LOCATION"
257         }
258       } else {
259         puts "Warning: MathJax is not used with pdf and will be ignored."
260       }
261     } else {
262       puts "\nWrong argument: $arg_n"
263       OCCDoc_PrintHelpMessage
264       return -1
265     }
266   }
267
268   # Check the existence of the necessary tools
269   set DOXYGEN_PATH  ""
270   set GRAPHVIZ_PATH ""
271   set INKSCAPE_PATH ""
272   set PDFLATEX_PATH ""
273   set HHC_PATH      ""
274
275   OCCDoc_DetectNecessarySoftware $DOXYGEN_PATH $GRAPHVIZ_PATH $INKSCAPE_PATH $HHC_PATH $PDFLATEX_PATH
276
277   if {$DOXYGEN_PATH == ""} {
278     puts " Aborting..."
279     return -1
280   }
281
282   if {"$::tcl_platform(platform)" == "windows"} {
283     if { ($GEN_MODE == "CHM_ONLY") && ($HHC_PATH == "") } {
284       puts " Aborting..."
285       return -1
286     }
287   }
288
289   if { ($PDFLATEX_PATH == "") && ($GEN_MODE == "PDF_ONLY") } {
290     puts " Aborting..."
291     return -1
292   }
293
294   # If we do not specify list for docfiles with -m argument,
295   # we assume that we have to generate all docfiles
296   if { [llength $DOCFILES] == 0 } {
297     if { $GEN_MODE != "PDF_ONLY" } {
298       set DOCFILES $available_docfiles
299     } else {
300       set DOCFILES $available_pdf
301     }
302   }
303
304   puts ""
305
306   # Start main activities
307   if { $GEN_MODE != "PDF_ONLY" } {
308     if { [OCCDoc_GetProdRootDir] == ""} {
309       OCCDoc_Main $DOC_TYPE $DOCFILES $MODULES $GEN_MODE $VERB_MODE $SEARCH_MODE $MATHJAX_LOCATION $GENERATE_PRODUCTS_REFMAN $DOXYGEN_PATH $GRAPHVIZ_PATH $INKSCAPE_PATH $HHC_PATH
310     } else {
311       if { $DOC_TYPE == "REFMAN" } {
312         if { $MODULES != "" } {
313           foreach module $MODULES {
314             OCCDoc_Main $DOC_TYPE $DOCFILES $module $GEN_MODE $VERB_MODE $SEARCH_MODE $MATHJAX_LOCATION $GENERATE_PRODUCTS_REFMAN $DOXYGEN_PATH $GRAPHVIZ_PATH $INKSCAPE_PATH $HHC_PATH
315           }
316         } else {
317           OCCDoc_Main $DOC_TYPE $DOCFILES $MODULES $GEN_MODE $VERB_MODE $SEARCH_MODE $MATHJAX_LOCATION $GENERATE_PRODUCTS_REFMAN $DOXYGEN_PATH $GRAPHVIZ_PATH $INKSCAPE_PATH $HHC_PATH
318         }
319       } else {
320         foreach md $DOCFILES {
321           OCCDoc_Main $DOC_TYPE $md $MODULES $GEN_MODE $VERB_MODE $SEARCH_MODE $MATHJAX_LOCATION $GENERATE_PRODUCTS_REFMAN $DOXYGEN_PATH $GRAPHVIZ_PATH $INKSCAPE_PATH $HHC_PATH
322         }
323       }
324     }
325   } else {
326     puts "Generating OCCT User Guides in PDF format..."
327     foreach pdf $DOCFILES {
328
329       puts "\nInfo: Processing file $pdf"
330
331       # Some values are hardcoded because they are related only to PDF generation
332       OCCDoc_Main "OVERVIEW" [list $pdf] {} "PDF_ONLY" $VERB_MODE "none" $MATHJAX_LOCATION "NO" $DOXYGEN_PATH $GRAPHVIZ_PATH $INKSCAPE_PATH $HHC_PATH
333     }
334     puts "\n[clock format [clock seconds] -format {%Y-%m-%d %H:%M}] Generation completed."
335   }
336 }
337
338 # Main procedure for documents compilation
339 proc OCCDoc_Main {docType {docfiles {}} {modules {}} generatorMode verboseMode searchMode mathjaxLocation generateProductsRefman DOXYGEN_PATH GRAPHVIZ_PATH INKSCAPE_PATH HHC_PATH} {
340
341   global available_docfiles
342   global available_pdf
343
344   set ROOTDIR    [OCCDoc_GetRootDir [OCCDoc_GetProdRootDir]]
345   set INDIR      [OCCDoc_GetDoxDir]
346   set OUTDIR     $ROOTDIR/doc
347   set PDFDIR     $OUTDIR/pdf
348   set UGDIR      $PDFDIR/user_guides
349   set DGDIR      $PDFDIR/dev_guides
350   set TAGFILEDIR $OUTDIR/refman
351   set HTMLDIR    $OUTDIR/overview/html
352   set LATEXDIR   $OUTDIR/overview/latex
353   set DOXYFILE   $OUTDIR/OCCT.cfg
354
355   # OUTDIR for products documentation should be separate directories for each components
356   if { [OCCDoc_GetProdRootDir] != ""} {
357     if { $docType == "REFMAN" } {
358       if { "$modules" != "" } {
359         source "[OCCDoc_GetSourceDir [OCCDoc_GetProdRootDir]]/VAS/${modules}.tcl"
360         set doc_component_name [${modules}:documentation_name]
361         set OUTDIR     $OUTDIR/$doc_component_name
362       }
363     } else {
364       if {[regexp {([^/]+)/([^/]+)/([^/]+)} $docfiles dump doc_type doc_component doc_name]} {
365         set PDFNAME [file rootname $doc_name]
366         set OUTDIR     $OUTDIR/$doc_component
367       } else {
368         error "Could not parse input path to *.md file: \"${docfiles}\""
369       }
370     }
371     set HTMLDIR    $OUTDIR/html
372     set LATEXDIR   $OUTDIR/latex
373     set DOXYFILE   $OUTDIR/OCCT.cfg
374     set TAGFILEDIR $OUTDIR/refman
375   }
376
377   # Create or cleanup the output folders
378   if { [string compare -nocase $generateProductsRefman "YES"] != 0 } {
379     if { ![file exists $OUTDIR] } {
380       file mkdir $OUTDIR
381     } 
382     if { ![file exists $HTMLDIR] } {
383       file mkdir $HTMLDIR
384     }
385     if { [OCCDoc_GetProdRootDir] == ""} {
386       if { ![file exists $PDFDIR] } {
387         file mkdir $PDFDIR
388       }
389       if { ![file exists $UGDIR] } {
390         file mkdir $UGDIR
391       }
392       if { ![file exists $DGDIR] } {
393         file mkdir $DGDIR
394       }
395     }
396
397     if { $generatorMode == "PDF_ONLY" } {
398       if { [file exists $LATEXDIR] } {
399         file delete -force $LATEXDIR
400       }
401       file mkdir $LATEXDIR
402     }
403   }
404   if { $docType == "REFMAN" } {
405     if { ![file exists $TAGFILEDIR] } {
406       file mkdir $TAGFILEDIR
407     }
408   }
409
410   # is MathJax HLink?
411   set mathjax_relative_location $mathjaxLocation
412   if { [file isdirectory "$mathjaxLocation"] } {
413     if { $generatorMode == "HTML_ONLY" } {
414       # related path
415       set mathjax_relative_location [OCCDoc_GetRelPath $HTMLDIR $mathjaxLocation]
416     } elseif { $generatorMode == "CHM_ONLY" } {
417       # absolute path
418       set mathjax_relative_location [file normalize $mathjaxLocation]
419     }
420   }
421
422   if { $generateProductsRefman == "YES" } {
423     set DOCDIR "$OUTDIR/refman"
424     puts "\nGenerating OCC Products Reference Manual\n"
425   } else {
426     if { $docType == "REFMAN"} {
427       set DOCDIR "$OUTDIR/refman"
428       puts "\nGenerating Open CASCADE Reference Manual\n"
429     } elseif { $docType == "OVERVIEW" } {
430       if { [OCCDoc_GetProdRootDir] == ""} {
431         set DOCDIR "$OUTDIR/overview"
432       } else {
433         set DOCDIR "$OUTDIR"
434       }
435       set FORMAT ""
436       if { ($generatorMode == "HTML_ONLY") || ($generatorMode == "CHM_ONLY") } {
437         if { $generatorMode == "HTML_ONLY" } { 
438           set FORMAT " in HTML format..."
439         } elseif { $generatorMode == "CHM_ONLY" } {
440           set FORMAT " in CHM format..."
441         }
442         puts "Generating OCCT User Guides$FORMAT\n"
443       }
444     } else {
445       puts "Error: Invalid documentation type: $docType. Can not process."
446       return -1
447     }
448   }
449
450   # Generate Doxyfile
451   puts "[clock format [clock seconds] -format {%Y-%m-%d %H:%M}] Generating Doxyfile..."
452
453   if { [OCCDoc_MakeDoxyfile $docType $DOCDIR $TAGFILEDIR $DOXYFILE $generatorMode $docfiles $modules $verboseMode $searchMode $HHC_PATH $mathjax_relative_location $GRAPHVIZ_PATH [OCCDoc_GetProdRootDir]] == -1 } {
454     return -1
455   }
456
457   # Run doxygen tool
458   set starttimestamp [clock format [clock seconds] -format {%Y-%m-%d %H:%M}]
459
460   if { ($generatorMode == "HTML_ONLY") || ($docType == "REFMAN") } {
461     set LOGPREFIX "html_"
462     puts "$starttimestamp Generating HTML files..."
463
464     # Copy index file to provide fast access to HTML documentation
465     file copy -force $INDIR/resources/index.html $DOCDIR/index.html
466   } elseif { $generatorMode == "CHM_ONLY" } {
467     set LOGPREFIX "chm_"
468     puts "$starttimestamp Generating CHM file..."
469   } elseif { $generatorMode == "PDF_ONLY" } {
470     set LOGPREFIX "[file rootname [file tail [lindex $docfiles 0]]]_"
471     puts "$starttimestamp Generating PDF file..."
472   }
473
474   # Clean logfiles  
475   set DOXYLOG $OUTDIR/${LOGPREFIX}doxygen_err.log
476   set DOXYOUT $OUTDIR/${LOGPREFIX}doxygen_out.log
477   file delete -force $DOXYLOG
478   file delete -force $DOXYOUT
479
480   set RESULT [catch {exec $DOXYGEN_PATH $DOXYFILE >> $DOXYOUT} DOX_ERROR] 
481   if {$RESULT != 0} {
482     set NbErrors [regexp -all -line {^\s*[^\s]+} $DOX_ERROR]
483     if {$NbErrors > 0} {
484       puts "Warning: Doxygen reported $NbErrors messages."
485       puts "See log in $DOXYLOG"
486       set DOX_ERROR_FILE [open $DOXYLOG "a"]
487       if {$generatorMode == "PDF_ONLY"} {
488         puts $DOX_ERROR_FILE "\n===================================================="
489         puts $DOX_ERROR_FILE "Logfile for $docfiles"
490         puts $DOX_ERROR_FILE "====================================================\n"
491       }
492       puts $DOX_ERROR_FILE $DOX_ERROR
493       close $DOX_ERROR_FILE
494     }
495   }
496
497   # Close the Doxygen application
498   after 300
499
500   # Start Post Processing
501   set curtime [clock format [clock seconds] -format {%Y-%m-%d %H:%M}]
502   if { $docType == "REFMAN" } {
503     # Post Process generated HTML pages and draw dependency graphs
504     if {[OCCDoc_PostProcessor $DOCDIR] == 0} {
505       puts "$curtime Generation completed."
506       puts "\nInfo: doxygen log file is located in:"
507       puts "${DOXYOUT}."
508       puts "\nReference Manual is generated in \n$DOCDIR"
509     }
510   } elseif { $docType == "OVERVIEW" } {
511     # Start PDF generation routine
512     if { $generatorMode == "PDF_ONLY" } {
513       set OS $::tcl_platform(platform)
514       if { $OS == "unix" } {
515         set PREFIX ".sh"
516       } elseif { $OS == "windows" } {
517         set PREFIX ".bat"
518       }
519
520       # Prepare a list of TeX files, generated by Doxygen
521       cd $LATEXDIR
522
523       set TEXFILES   [glob $LATEXDIR -type f -directory $LATEXDIR -tails "*.tex" ]
524       foreach path $TEXFILES {
525         if { [string compare -nocase $path $LATEXDIR] == 0 } {
526           set DEL_IDX [lsearch $TEXFILES $path]
527           if { $DEL_IDX != -1 } {
528             set TEXFILES [lreplace $TEXFILES $DEL_IDX $DEL_IDX]
529           }
530         }
531       }
532       set TEXFILES   [string map [list refman.tex ""] $TEXFILES]
533       if {$verboseMode == "YES"} {
534         puts "Info: Preprocessing generated TeX files..."
535       }
536       OCCDoc_ProcessTex $TEXFILES $LATEXDIR $verboseMode
537
538       if {$verboseMode == "YES"} {
539         puts "Info: Converting SVG images to PNG format..."
540       }
541
542       if { $INKSCAPE_PATH != "" } {
543         OCCDoc_ProcessSvg $LATEXDIR $verboseMode
544       } else {
545         puts "Warning: SVG images will be lost in PDF documents."
546       }
547
548       if {$verboseMode == "YES"} {
549         puts "Info: Generating PDF file from TeX files..."
550       }
551       foreach TEX $TEXFILES {
552         # Rewrite existing REFMAN.tex file...
553         set TEX [lindex [split $TEX "."] 0]
554
555         if {$verboseMode == "YES"} {
556           puts "Info: Generating PDF file from $TEX..."
557         }
558
559         OCCDoc_MakeRefmanTex $TEX $LATEXDIR $verboseMode $available_pdf
560
561         if {"$::tcl_platform(platform)" == "windows"} {
562           set is_win "yes"
563         } else {
564           set is_win "no"
565         }
566         if {$verboseMode == "YES"} {
567           # ...and use it to generate PDF from TeX...
568           if {$is_win == "yes"} {
569             puts "Info: Executing $LATEXDIR/make.bat..."
570           } else {
571             puts "Info: Executing $LATEXDIR/Makefile..."
572           }
573         }
574
575         set PDFLOG $OUTDIR/${LOGPREFIX}pdflatex_err.log
576         set PDFOUT $OUTDIR/${LOGPREFIX}pdflatex_out.log
577         file delete -force $PDFLOG
578         file delete -force $PDFOUT
579
580         if {"$is_win" == "yes"} {
581           set RESULT [catch {eval exec [auto_execok $LATEXDIR/make.bat] >> "$PDFOUT"} LaTeX_ERROR]
582         } else {
583           set RESULT [catch {eval exec "make -f $LATEXDIR/Makefile" >> "$PDFOUT"} LaTeX_ERROR]
584
585           # Small workaround for *nix stations
586           set prev_loc [pwd]
587           cd $LATEXDIR
588           set RESULT [catch {eval exec "pdflatex refman.tex" >> "$PDFOUT"} LaTeX_ERROR]
589           cd $prev_loc
590         }
591
592         if {$RESULT != 0} {
593           set NbErrors [regexp -all -line {^\s*[^\s]+} $LaTeX_ERROR]
594           if {$NbErrors > 0} {
595             puts "Warning: PDFLaTeX reported $NbErrors messages.\nSee log in $PDFLOG"
596             set LaTeX_ERROR_FILE [open $PDFLOG "a+"]
597             puts $LaTeX_ERROR_FILE "\n===================================================="
598             puts $LaTeX_ERROR_FILE "Logfile of file $TEX:"
599             puts $LaTeX_ERROR_FILE "====================================================\n"
600             puts $LaTeX_ERROR_FILE $LaTeX_ERROR
601             close $LaTeX_ERROR_FILE
602           }
603         }
604
605         # ...and place it to the specific folder
606         if {![file exists "$LATEXDIR/refman.pdf"]} {
607           puts "Fatal: PDFLaTeX failed to create output file, stopping!"
608           return -1
609         }
610
611         set destFolder $PDFDIR
612         set parsed_string [split $TEX "_"]
613         if { [OCCDoc_GetProdRootDir] == ""} {
614           if { [lsearch $parsed_string "tutorial"] != -1 } {
615             set TEX [string map [list occt__ occt_] $TEX]
616             set destFolder $PDFDIR
617           } elseif { [lsearch $parsed_string "user"] != -1 } {
618             set TEX [string map [list user_guides__ ""] $TEX]
619             set destFolder $UGDIR
620           } elseif { [lsearch $parsed_string "dev"]  != -1 } {
621             set TEX [string map [list dev_guides__ ""] $TEX]
622             set destFolder $DGDIR
623           }
624         } else {
625           set destFolder $OUTDIR
626           set TEX "$PDFNAME"
627         }
628         file rename -force $LATEXDIR/refman.pdf "$destFolder/$TEX.pdf"
629         puts "Generated $destFolder/$TEX.pdf"
630       }
631     } elseif { $generatorMode == "CHM_ONLY" } {
632       if { [OCCDoc_GetProdRootDir] == ""} {
633         file rename $OUTDIR/overview.chm $OUTDIR/occt_overview.chm
634       } else {
635         file rename -force $ROOTDIR/doc/overview.chm $OUTDIR/occt_overview.chm
636       }
637     }
638     cd $INDIR
639
640     if { $generatorMode == "HTML_ONLY" } {
641       puts "HTML documentation is generated in \n$DOCDIR"
642     } elseif { $generatorMode == "CHM_ONLY" } {
643       puts "Generated CHM documentation is in \n$OUTDIR/overview.chm"
644     }
645   }
646
647   # Remove temporary Doxygen files
648   set deleteList [glob -nocomplain -type f "*.tmp"]
649   foreach file $deleteList {
650     file delete $file
651   }
652
653   return 0
654 }
655
656 # Generates Doxygen configuration file for Overview documentation
657 proc OCCDoc_MakeDoxyfile {docType outDir tagFileDir {doxyFileName} {generatorMode ""} {DocFilesList {}} {ModulesList {}} verboseMode searchMode hhcPath mathjaxLocation graphvizPath productsPath} {
658   set inputDir      [OCCDoc_GetDoxDir [OCCDoc_GetProdRootDir]]
659
660   set TEMPLATES_DIR [OCCDoc_GetDoxDir]/resources
661   set occt_version  [OCCDoc_DetectCasVersion]
662
663   # Delete existent doxyfile
664   file delete $doxyFileName
665
666   # Copy specific template to the target folder
667   if { $docType == "REFMAN" } {
668     file copy "$TEMPLATES_DIR/occt_rm.doxyfile" $doxyFileName
669   } elseif { $docType == "OVERVIEW" } {
670     if { $generatorMode == "HTML_ONLY" || $generatorMode == "CHM_ONLY" } {
671       file copy "$TEMPLATES_DIR/occt_ug_html.doxyfile" $doxyFileName
672     } elseif { $generatorMode == "PDF_ONLY"} {
673       file copy "$TEMPLATES_DIR/occt_ug_pdf.doxyfile" $doxyFileName
674     } else {
675       puts "Error: Unknown generation mode"
676       return -1
677     }
678   } else {
679     puts "Error: Cannot generate unknown document type"
680     return -1
681   }
682
683   set doxyFile [open $doxyFileName "a"]
684   # Write specific options
685   if { $docType == "REFMAN" } {
686
687     # Load lists of modules scripts
688     if { $productsPath == "" } {
689       set modules_scripts [glob -nocomplain -type f -directory "[OCCDoc_GetSourceDir $productsPath]/OS/" *.tcl]
690     } else {
691       set modules_scripts [glob -nocomplain -type f -directory "[OCCDoc_GetSourceDir $productsPath]/VAS/" *.tcl]
692     }
693     if { [llength $modules_scripts] != 0} {
694       foreach module_file $modules_scripts {
695         source $module_file
696       }
697     }
698
699     set ALL_MODULES [OCCDoc_GetModulesList $productsPath]
700     if { [llength $ModulesList] == 0 } {
701       # by default take all modules
702       set modules $ALL_MODULES
703     } else {
704       set modules $ModulesList
705     }
706
707     # Detect invalid names of modules
708     foreach module $modules {
709       if { $module == "" } {
710         continue
711       }
712       if {[lsearch $ALL_MODULES $module] == -1 } {
713         puts "Error: No module $module is known. Aborting..."
714         return -1
715       }
716     }
717
718     # Set context
719     set one_module [expr [llength $modules] == 1]
720     if { $one_module } {
721       set title "OCCT [$modules:name]"
722       set name $modules
723     } else {
724       set title "Open CASCADE Technology"
725       set name OCCT
726     }
727
728     # Get list of header files in the specified modules
729     set filelist {}
730     foreach module $modules {
731       if { $module == "" } {
732         continue
733       }
734       foreach tk [$module:toolkits] {
735         foreach pk [split [OCCDoc_GetPackagesList [OCCDoc_Locate $tk $productsPath]]] {
736           if { [llength $pk] != "{}" } {
737             lappend filelist [OCCDoc_GetHeadersList "p" "$pk" "$productsPath"]
738           }
739         }
740       }
741     }
742
743     # Filter out files Handle_*.hxx and *.lxx
744     set hdrlist {}
745     foreach fileset $filelist {
746       set hdrset {}
747       foreach hdr $fileset {
748         if { ! [regexp {Handle_.*[.]hxx} $hdr] && ! [regexp {.*[.]lxx} $hdr] } {
749           lappend hdrset $hdr
750         }
751       }
752       lappend hdrlist $hdrset
753     }
754     set filelist $hdrlist
755
756     set doxyFile [open $doxyFileName "a"]
757   
758     puts $doxyFile "PROJECT_NAME           = \"$title\""
759     puts $doxyFile "PROJECT_NUMBER         = $occt_version"
760     puts $doxyFile "OUTPUT_DIRECTORY       = $outDir/."
761     puts $doxyFile "GENERATE_TAGFILE       = $outDir/${name}.tag"
762
763     if { [string tolower $searchMode] == "none" } {
764       puts $doxyFile "SEARCHENGINE           = NO"
765       puts $doxyFile "SERVER_BASED_SEARCH    = NO"
766       puts $doxyFile "EXTERNAL_SEARCH        = NO"
767     } else {
768       puts $doxyFile "SEARCHENGINE           = YES"
769       if { [string tolower $searchMode] == "local" } {
770         puts $doxyFile "SERVER_BASED_SEARCH    = NO"
771         puts $doxyFile "EXTERNAL_SEARCH        = NO"
772       } elseif { [string tolower $searchMode] == "server" } {
773         puts $doxyFile "SERVER_BASED_SEARCH    = YES"
774         puts $doxyFile "EXTERNAL_SEARCH        = NO"
775       } elseif { [string tolower $searchMode] == "external" } {
776         puts $doxyFile "SERVER_BASED_SEARCH    = YES"
777         puts $doxyFile "EXTERNAL_SEARCH        = YES"
778       } else {
779         puts "Error: Wrong search engine type: $searchMode."
780         close $doxyFile 
781         return -1
782       }
783     }
784
785     puts $doxyFile "DOTFILE_DIRS             = $outDir/html"
786     puts $doxyFile "DOT_PATH                 = $graphvizPath"
787     puts $doxyFile "INCLUDE_PATH             = [OCCDoc_GetSourceDir $productsPath]"
788     
789     # list of files to generate
790     set mainpage [OCCDoc_MakeMainPage $outDir $outDir/$name.dox $modules $productsPath]
791     puts $doxyFile ""
792     puts $doxyFile "INPUT    = $mainpage \\"
793     foreach header $filelist {
794       puts $doxyFile "               $header \\"
795     }
796
797     puts $doxyFile "MATHJAX_FORMAT         = HTML-CSS"
798     puts $doxyFile "MATHJAX_RELPATH        = ${mathjaxLocation}"
799
800     puts $doxyFile ""
801
802   } elseif { $docType == "OVERVIEW" } {
803
804     # Add common options for generation of Overview and User Guides
805     puts $doxyFile "PROJECT_NUMBER         = $occt_version"
806     puts $doxyFile "OUTPUT_DIRECTORY       = $outDir/."
807     puts $doxyFile "PROJECT_LOGO           = [OCCDoc_GetDoxDir]/resources/occ_logo.png"
808
809     set PARAM_INPUT "INPUT                 ="
810     set PARAM_IMAGEPATH "IMAGE_PATH        = [OCCDoc_GetDoxDir]/resources/ "
811     foreach docFile $DocFilesList {
812       set NEW_IMG_PATH "$inputDir/$docFile"
813       if { [string compare $NEW_IMG_PATH [OCCDoc_GetRootDir $productsPath]] != 0 } {
814         set img_string [file dirname $NEW_IMG_PATH]/images
815         if { [file exists $img_string] } {
816           append PARAM_IMAGEPATH " $img_string"
817         }
818       }
819       append PARAM_INPUT " " $inputDir/$docFile
820     }
821     puts $doxyFile $PARAM_INPUT
822     puts $doxyFile $PARAM_IMAGEPATH
823
824     # Add document type-specific options
825     if { $generatorMode == "HTML_ONLY"} {
826       # generate tree view
827       puts $doxyFile "GENERATE_TREEVIEW      = YES"
828
829       # Set a reference to a TAGFILE
830       if { $tagFileDir != "" } {
831         if {[file exists $tagFileDir/OCCT.tag] == 1} {
832           #set tagPath [OCCDoc_GetRelPath $tagFileDir $outDir/html]
833           set tagPath $tagFileDir
834           puts $doxyFile "TAGFILES               = $tagFileDir/OCCT.tag=../../refman/html"
835         }
836       }
837       # HTML Search engine options
838       if { [string tolower $searchMode] == "none" } {
839         puts $doxyFile "SEARCHENGINE           = NO"
840         puts $doxyFile "SERVER_BASED_SEARCH    = NO"
841         puts $doxyFile "EXTERNAL_SEARCH        = NO"
842       } else {
843         puts $doxyFile "SEARCHENGINE           = YES"
844         if { [string tolower $searchMode] == "local" } {
845           puts $doxyFile "SERVER_BASED_SEARCH    = NO"
846           puts $doxyFile "EXTERNAL_SEARCH        = NO"
847         } elseif { [string tolower $searchMode] == "server" } {
848           puts $doxyFile "SERVER_BASED_SEARCH    = YES"
849           puts $doxyFile "EXTERNAL_SEARCH        = NO"
850         } elseif { [string tolower $searchMode] == "external" } {
851           puts $doxyFile "SERVER_BASED_SEARCH    = YES"
852           puts $doxyFile "EXTERNAL_SEARCH        = YES"
853         } else {
854           puts "Error: Wrong search engine type: $searchMode."
855           close $doxyFile 
856           return -1
857         }
858       }
859     } elseif { $generatorMode == "CHM_ONLY"} {
860       # specific options for CHM file generation
861       puts $doxyFile "GENERATE_TREEVIEW      = NO"
862       puts $doxyFile "SEARCHENGINE           = NO"
863       puts $doxyFile "GENERATE_HTMLHELP      = YES"
864       puts $doxyFile "CHM_FILE               = ../../overview.chm"
865       puts $doxyFile "HHC_LOCATION           = \"$hhcPath\""
866       puts $doxyFile "DISABLE_INDEX          = YES"
867     }
868
869     # Formula options
870     puts $doxyFile "MATHJAX_RELPATH        = ${mathjaxLocation}"
871   }
872
873   close $doxyFile
874   return 0
875 }