]> git.lyx.org Git - lyx.git/blob - lib/configure.py
Add recognition to eLyXer
[lyx.git] / lib / configure.py
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # file configure.py
5 # This file is part of LyX, the document processor.
6 # Licence details can be found in the file COPYING.
7
8 # \author Bo Peng
9 # Full author contact details are available in file CREDITS.
10
11 import sys, os, re, shutil, glob, logging
12
13 # set up logging
14 logging.basicConfig(level = logging.DEBUG,
15     format = '%(levelname)s: %(message)s', # ignore application name
16     filename = 'configure.log',
17     filemode = 'w')
18 #
19 # Add a handler to log to console
20 console = logging.StreamHandler()
21 console.setLevel(logging.INFO) # the console only print out general information
22 formatter = logging.Formatter('%(message)s') # only print out the message itself
23 console.setFormatter(formatter)
24 logger = logging.getLogger('LyX')
25 logger.addHandler(console)
26
27 def writeToFile(filename, lines, append = False):
28     " utility function: write or append lines to filename "
29     if append:
30         file = open(filename, 'a')
31     else:
32         file = open(filename, 'w')
33     file.write(lines)
34     file.close()
35
36
37 def addToRC(lines):
38     ''' utility function: shortcut for appending lines to outfile
39         add newline at the end of lines.
40     '''
41     if lines.strip() != '':
42         writeToFile(outfile, lines + '\n', append = True)
43         logger.debug('Add to RC:\n' + lines + '\n\n')
44
45
46 def removeFiles(filenames):
47     '''utility function: 'rm -f'
48         ignore errors when file does not exist, or is a directory.
49     '''
50     for file in filenames:
51         try:
52             os.remove(file)
53             logger.debug('Removing file %s' % file)
54         except:
55             logger.debug('Failed to remove file %s' % file)
56             pass
57
58
59 def cmdOutput(cmd):
60     '''utility function: run a command and get its output as a string
61         cmd: command to run
62     '''
63     fout = os.popen(cmd)
64     output = fout.read()
65     fout.close()
66     return output.strip()
67
68
69 def setEnviron():
70     ''' I do not really know why this is useful, but we might as well keep it.
71         NLS nuisances.
72         Only set these to C if already set.  These must not be set unconditionally
73         because not all systems understand e.g. LANG=C (notably SCO).
74         Fixing LC_MESSAGES prevents Solaris sh from translating var values in set!
75         Non-C LC_CTYPE values break the ctype check.
76     '''
77     os.environ['LANG'] = os.getenv('LANG', 'C')
78     os.environ['LC'] = os.getenv('LC_ALL', 'C')
79     os.environ['LC_MESSAGE'] = os.getenv('LC_MESSAGE', 'C')
80     os.environ['LC_CTYPE'] = os.getenv('LC_CTYPE', 'C')
81
82
83 def createDirectories():
84     ''' Create the build directories if necessary '''
85     for dir in ['bind', 'clipart', 'doc', 'examples', 'images', 'kbd', \
86         'layouts', 'scripts', 'templates', 'ui' ]:
87         if not os.path.isdir( dir ):
88             try:
89                 os.mkdir( dir)
90                 logger.debug('Create directory %s.' % dir)
91             except:
92                 logger.error('Failed to create directory %s.' % dir)
93                 sys.exit(1)
94
95
96 def checkTeXPaths():
97     ''' Determine the path-style needed by the TeX engine on Win32 (Cygwin) '''
98     windows_style_tex_paths = ''
99     if os.name == 'nt' or sys.platform == 'cygwin':
100         from tempfile import mkstemp
101         fd, tmpfname = mkstemp(suffix='.ltx')
102         if os.name == 'nt':
103             inpname = tmpfname.replace('\\', '/')
104         else:
105             inpname = cmdOutput('cygpath -m ' + tmpfname)
106         logname = os.path.basename(inpname.replace('.ltx', '.log'))
107         inpname = inpname.replace('~', '\\string~')
108         os.write(fd, r'\relax')
109         os.close(fd)
110         latex_out = cmdOutput(r'latex "\nonstopmode\input{%s}"' % inpname)
111         if 'Error' in latex_out:
112             logger.warning("configure: TeX engine needs posix-style paths in latex files")
113             windows_style_tex_paths = 'false'
114         else:
115             logger.info("configure: TeX engine needs windows-style paths in latex files")
116             windows_style_tex_paths = 'true'
117         removeFiles([tmpfname, logname, 'texput.log'])
118     return windows_style_tex_paths
119
120
121 ## Searching some useful programs
122 def checkProg(description, progs, rc_entry = [], path = [], not_found = ''):
123     '''
124         This function will search a program in $PATH plus given path
125         If found, return directory and program name (not the options).
126
127         description: description of the program
128
129         progs: check programs, for each prog, the first word is used
130             for searching but the whole string is used to replace
131             %% for a rc_entry. So, feel free to add '$$i' etc for programs.
132
133         path: additional pathes
134
135         rc_entry: entry to outfile, can be
136             1. emtpy: no rc entry will be added
137             2. one pattern: %% will be replaced by the first found program,
138                 or '' if no program is found.
139             3. several patterns for each prog and not_found. This is used 
140                 when different programs have different usages. If you do not 
141                 want not_found entry to be added to the RC file, you can specify 
142                 an entry for each prog and use '' for the not_found entry.
143
144         not_found: the value that should be used instead of '' if no program
145             was found
146
147     '''
148     # one rc entry for each progs plus not_found entry
149     if len(rc_entry) > 1 and len(rc_entry) != len(progs) + 1:
150         logger.error("rc entry should have one item or item for each prog and not_found.")
151         sys.exit(2)
152     logger.info('checking for ' + description + '...')
153     ## print '(' + ','.join(progs) + ')',
154     for idx in range(len(progs)):
155         # ac_prog may have options, ac_word is the command name
156         ac_prog = progs[idx]
157         ac_word = ac_prog.split(' ')[0]
158         msg = '+checking for "' + ac_word + '"... '
159         path = os.environ["PATH"].split(os.pathsep) + path
160         extlist = ['']
161         if os.environ.has_key("PATHEXT"):
162             extlist = extlist + os.environ["PATHEXT"].split(os.pathsep)
163         for ac_dir in path:
164             for ext in extlist:
165                 if os.path.isfile( os.path.join(ac_dir, ac_word + ext) ):
166                     logger.info(msg + ' yes')
167                     # write rc entries for this command
168                     if len(rc_entry) == 1:
169                         addToRC(rc_entry[0].replace('%%', ac_prog))
170                     elif len(rc_entry) > 1:
171                         addToRC(rc_entry[idx].replace('%%', ac_prog))
172                     return [ac_dir, ac_word]
173         # if not successful
174         logger.info(msg + ' no')
175     # write rc entries for 'not found'
176     if len(rc_entry) > 0:  # the last one.
177         addToRC(rc_entry[-1].replace('%%', not_found))
178     return ['', not_found]
179
180
181 def checkViewer(description, progs, rc_entry = [], path = []):
182     ''' The same as checkProg, but for viewers and editors '''
183     return checkProg(description, progs, rc_entry, path, not_found = 'auto')
184
185
186 def checkDTLtools():
187     ''' Check whether DTL tools are available (Windows only) '''
188     # Find programs! Returned path is not used now
189     if ((os.name == 'nt' or sys.platform == 'cygwin') and
190             checkProg('DVI to DTL converter', ['dv2dt']) != ['', ''] and
191             checkProg('DTL to DVI converter', ['dt2dv']) != ['', '']):
192         dtl_tools = True
193     else:
194         dtl_tools = False
195     return dtl_tools
196
197
198 def checkLatex(dtl_tools):
199     ''' Check latex, return lyx_check_config '''
200     path, LATEX = checkProg('a Latex2e program', ['latex $$i', 'platex $$i', 'latex2e $$i'])
201     path, PPLATEX = checkProg('a DVI postprocessing program', ['pplatex $$i'])
202     #-----------------------------------------------------------------
203     path, PLATEX = checkProg('pLaTeX, the Japanese LaTeX', ['platex $$i'])
204     if PLATEX != '':
205         # check if PLATEX is pLaTeX2e
206         writeToFile('chklatex.ltx', '''
207 \\nonstopmode
208 \\@@end
209 ''')
210         # run platex on chklatex.ltx and check result
211         if cmdOutput(PLATEX + ' chklatex.ltx').find('pLaTeX2e') != -1:
212             # We have the Japanese pLaTeX2e
213             addToRC(r'\converter platex   dvi       "%s"   "latex"' % PLATEX)
214             LATEX = PLATEX
215         else:
216             PLATEX = ''
217             removeFiles(['chklatex.ltx', 'chklatex.log'])
218     #-----------------------------------------------------------------
219     # use LATEX to convert from latex to dvi if PPLATEX is not available    
220     if PPLATEX == '':
221         PPLATEX = LATEX
222     if dtl_tools:
223         # Windows only: DraftDVI
224         addToRC(r'''\converter latex      dvi2       "%s"       "latex"
225 \converter dvi2       dvi        "python -tt $$s/scripts/clean_dvi.py $$i $$o"  ""''' % PPLATEX)
226     else:
227         addToRC(r'\converter latex      dvi        "%s" "latex"' % PPLATEX)
228     # no latex
229     if LATEX != '':
230         # Check if latex is usable
231         writeToFile('chklatex.ltx', '''
232 \\nonstopmode\\makeatletter
233 \\ifx\\undefined\\documentclass\\else
234   \\message{ThisIsLaTeX2e}
235 \\fi
236 \\@@end
237 ''')
238         # run latex on chklatex.ltx and check result
239         if cmdOutput(LATEX + ' chklatex.ltx').find('ThisIsLaTeX2e') != -1:
240             # valid latex2e
241             return LATEX
242         else:
243             logger.warning("Latex not usable (not LaTeX2e) ")
244         # remove temporary files
245         removeFiles(['chklatex.ltx', 'chklatex.log'])
246     return ''
247
248
249 def checkFormatEntries(dtl_tools):  
250     ''' Check all formats (\Format entries) '''
251     checkViewer('a Tgif viewer and editor', ['tgif'],
252         rc_entry = [r'\Format tgif       obj     Tgif                   "" "%%" "%%"    "vector"'])
253     #
254     checkViewer('a FIG viewer and editor', ['xfig', 'jfig3-itext.jar', 'jfig3.jar'],
255         rc_entry = [r'\Format fig        fig     FIG                    "" "%%" "%%"    "vector"'])
256     #
257     checkViewer('a Dia viewer and editor', ['dia'],
258         rc_entry = [r'\Format dia        dia     DIA                    "" "%%" "%%"    "vector"'])
259     #
260     checkViewer('a Grace viewer and editor', ['xmgrace'],
261         rc_entry = [r'\Format agr        agr     Grace                  "" "%%" "%%"    "vector"'])
262     #
263     checkViewer('a FEN viewer and editor', ['xboard -lpf $$i -mode EditPosition'],
264         rc_entry = [r'\Format fen        fen     FEN                    "" "%%" "%%"    ""'])
265     #
266     path, iv = checkViewer('a raster image viewer', ['xv', 'kview', 'gimp-remote', 'gimp'])
267     path, ie = checkViewer('a raster image editor', ['gimp-remote', 'gimp'])
268     addToRC(r'''\Format bmp        bmp     BMP                    "" "%s"       "%s"    ""
269 \Format gif        gif     GIF                    "" "%s"       "%s"    ""
270 \Format jpg        jpg     JPEG                   "" "%s"       "%s"    ""
271 \Format pbm        pbm     PBM                    "" "%s"       "%s"    ""
272 \Format pgm        pgm     PGM                    "" "%s"       "%s"    ""
273 \Format png        png     PNG                    "" "%s"       "%s"    ""
274 \Format ppm        ppm     PPM                    "" "%s"       "%s"    ""
275 \Format tiff       tif     TIFF                   "" "%s"       "%s"    ""
276 \Format xbm        xbm     XBM                    "" "%s"       "%s"    ""
277 \Format xpm        xpm     XPM                    "" "%s"       "%s"    ""''' % \
278         (iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie, iv, ie) )
279     #
280     checkViewer('a text editor', ['sensible-editor', 'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
281         'nedit', 'gedit', 'notepad'],
282         rc_entry = [r'''\Format asciichess asc    "Plain text (chess output)"  "" ""    "%%"    ""
283 \Format asciiimage asc    "Plain text (image)"         "" ""    "%%"    ""
284 \Format asciixfig  asc    "Plain text (Xfig output)"   "" ""    "%%"    ""
285 \Format dateout    tmp    "date (output)"         "" "" "%%"    ""
286 \Format docbook    sgml    DocBook                B  "" "%%"    "document"
287 \Format docbook-xml xml   "Docbook (XML)"         "" "" "%%"    "document"
288 \Format dot        dot    "Graphviz Dot"          "" "" "%%"    "vector"
289 \Format platex     tex    "LaTeX (pLaTeX)"        "" "" "%%"    "document"
290 \Format literate   nw      NoWeb                  N  "" "%%"    "document"
291 \Format lilypond   ly     "LilyPond music"        "" "" "%%"    "vector"
292 \Format latex      tex    "LaTeX (plain)"         L  "" "%%"    "document"
293 \Format pdflatex   tex    "LaTeX (pdflatex)"      "" "" "%%"    "document"
294 \Format xetex      tex    "LaTeX (XeTeX)"         "" "" "%%"    "document"
295 \Format text       txt    "Plain text"            a  "" "%%"    "document"
296 \Format text2      txt    "Plain text (pstotext)" "" "" "%%"    "document"
297 \Format text3      txt    "Plain text (ps2ascii)" "" "" "%%"    "document"
298 \Format text4      txt    "Plain text (catdvi)"   "" "" "%%"    "document"
299 \Format textparagraph txt "Plain Text, Join Lines" "" ""        "%%"    "document"''' ])
300  #
301     checkViewer('a BibTeX editor', ['sensible-editor', 'jabref', 'JabRef', \
302         'pybliographic', 'bibdesk', 'gbib', 'kbib', \
303         'kbibtex', 'sixpack', 'bibedit', 'tkbibtex' \
304         'xemacs', 'gvim', 'kedit', 'kwrite', 'kate', \
305         'nedit', 'gedit', 'notepad'],
306         rc_entry = [r'''\Format bibtex bib    "BibTeX"         "" ""    "%%"    ""''' ])
307     #
308     #checkProg('a Postscript interpreter', ['gs'],
309     #  rc_entry = [ r'\ps_command "%%"' ])
310     checkViewer('a Postscript previewer', ['kghostview', 'okular', 'evince', 'gv', 'ghostview -swap'],
311         rc_entry = [r'''\Format eps        eps     EPS                    "" "%%"       ""      "vector"
312 \Format ps         ps      Postscript             t  "%%"       ""      "document,vector"'''])
313     #
314     checkViewer('a PDF previewer', ['kpdf', 'okular', 'evince', 'kghostview', 'xpdf', 'acrobat', 'acroread', \
315                     'gv', 'ghostview'],
316         rc_entry = [r'''\Format pdf        pdf    "PDF (ps2pdf)"          P  "%%"       ""      "document,vector"
317 \Format pdf2       pdf    "PDF (pdflatex)"        F  "%%"       ""      "document,vector"
318 \Format pdf3       pdf    "PDF (dvipdfm)"         m  "%%"       ""      "document,vector"
319 \Format pdf4       pdf    "PDF (XeTeX)"           X  "%%"       ""      "document,vector"'''])
320     #
321     checkViewer('a DVI previewer', ['xdvi', 'kdvi', 'okular'],
322         rc_entry = [r'\Format dvi        dvi     DVI                    D  "%%" ""      "document,vector"'])
323     if dtl_tools:
324         # Windows only: DraftDVI
325         addToRC(r'\Format dvi2       dvi     DraftDVI               ""  ""      ""      "vector"')
326     #
327     checkViewer('an HTML previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
328         rc_entry = [r'\Format html       html    HTML                   H  "%%" ""      "document"'])
329     #
330     checkViewer('Noteedit', ['noteedit'],
331         rc_entry = [r'\Format noteedit   not     Noteedit               "" "%%" "%%"    "vector"'])
332     #
333     checkViewer('an OpenDocument viewer', ['swriter', 'oowriter'],
334         rc_entry = [r'\Format odt        odt     OpenDocument           "" "%%" "%%"    "document,vector"'])
335     #
336     # entried that do not need checkProg
337     addToRC(r'''\Format date       ""     "date command"          "" "" ""      ""
338 \Format csv        csv    "Table (CSV)"  "" ""  ""      "document"
339 \Format fax        ""      Fax                    "" "" ""      "document"
340 \Format lyx        lyx     LyX                    "" "" ""      ""
341 \Format lyx13x     lyx13  "LyX 1.3.x"             "" "" ""      "document"
342 \Format lyx14x     lyx14  "LyX 1.4.x"             "" "" ""      "document"
343 \Format lyx15x     lyx15  "LyX 1.5.x"             "" "" ""      "document"
344 \Format lyx16x     lyx16  "LyX 1.6.x"             "" "" ""      "document"
345 \Format clyx       cjklyx "CJK LyX 1.4.x (big5)"  "" "" ""      "document"
346 \Format jlyx       cjklyx "CJK LyX 1.4.x (euc-jp)" "" ""        ""      "document"
347 \Format klyx       cjklyx "CJK LyX 1.4.x (euc-kr)" "" ""        ""      "document"
348 \Format lyxpreview lyxpreview "LyX Preview"       "" "" ""      ""
349 \Format lyxpreview-platex lyxpreview-platex "LyX Preview (pLaTeX)"       "" ""  ""      ""
350 \Format pdftex     pdftex_t PDFTEX                "" "" ""      ""
351 \Format program    ""      Program                "" "" ""      ""
352 \Format pstex      pstex_t PSTEX                  "" "" ""      ""
353 \Format rtf        rtf    "Rich Text Format"      "" "" ""      "document,vector"
354 \Format sxw        sxw    "OpenOffice.Org (sxw)"  ""  ""        ""      "document,vector"
355 \Format wmf        wmf    "Windows Metafile"      "" "" ""      "vector"
356 \Format emf        emf    "Enhanced Metafile"     "" "" ""      "vector"
357 \Format word       doc    "MS Word"               W  "" ""      "document,vector"
358 \Format wordhtml   html   "HTML (MS Word)"        "" "" ""      "document"
359 ''')
360
361
362 def checkConverterEntries():
363     ''' Check all converters (\converter entries) '''
364     checkProg('the pdflatex program', ['pdflatex $$i'],
365         rc_entry = [ r'\converter pdflatex   pdf2       "%%"    "latex"' ])
366
367     checkProg('XeTeX', ['xelatex $$i'],
368         rc_entry = [ r'\converter xetex      pdf4       "%%"    "latex"' ])
369     
370     ''' If we're running LyX in-place then tex2lyx will be found in
371             ../src/tex2lyx. Add this directory to the PATH temporarily and
372             search for tex2lyx.
373             Use PATH to avoid any problems with paths-with-spaces.
374     '''
375     path_orig = os.environ["PATH"]
376     os.environ["PATH"] = os.path.join('..', 'src', 'tex2lyx') + \
377         os.pathsep + path_orig
378
379     checkProg('a LaTeX/Noweb -> LyX converter', ['tex2lyx', 'tex2lyx' + version_suffix],
380         rc_entry = [r'''\converter latex      lyx        "%% -f $$i $$o"        ""
381 \converter literate   lyx        "%% -n -f $$i $$o"     ""'''])
382
383     os.environ["PATH"] = path_orig
384
385     #
386     checkProg('a Noweb -> LaTeX converter', ['noweave -delay -index $$i > $$o'],
387         rc_entry = [r'''\converter literate   latex      "%%"   ""
388 \converter literate   pdflatex      "%%"        ""'''])
389     #
390     path, elyx = checkProg('eLyXer converter', ['elyxer $$i $$o'],
391         rc_entry = [ r'\converter lyx elyxhtml "%%" ""' ] )
392     if elyx.find('elyxer') >= 0 :
393       addToRC(r'''\copier    elyxhtml       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
394       checkViewer('an eLyXer previewer', ['firefox', 'mozilla file://$$p$$i', 'netscape'],
395           rc_entry = [r'\Format elyxhtml   html    "HTML (eLyXer)"        e  "%%"       ""      "document"'])
396
397     #
398     checkProg('an HTML -> LaTeX converter', ['html2latex $$i', 'gnuhtml2latex $$i', \
399         'htmltolatex -input $$i -output $$o', 'java -jar htmltolatex.jar -input $$i -output $$o'],
400         rc_entry = [ r'\converter html       latex      "%%"    ""' ])
401     #
402     checkProg('an MS Word -> LaTeX converter', ['wvCleanLatex $$i $$o'],
403         rc_entry = [ r'\converter word       latex      "%%"    ""' ])
404     # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
405     path, htmlconv = checkProg('a LaTeX -> HTML converter', ['htlatex $$i', 'htlatex.sh $$i', \
406         '/usr/share/tex4ht/htlatex $$i', 'tth  -t -e2 -L$$b < $$i > $$o', \
407         'latex2html -no_subdir -split 0 -show_section_numbers $$i', 'hevea -s $$i'],
408         rc_entry = [ r'\converter latex      html       "%%"    "needaux"' ])
409     if htmlconv.find('htlatex') >= 0 or htmlconv == 'latex2html':
410       addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
411     else:
412       addToRC(r'''\copier    html       "python -tt $$s/scripts/ext_copy.py $$i $$o"''')
413
414     # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
415     path, htmlconv = checkProg('a LaTeX -> MS Word converter', ["htlatex $$i 'html,word' 'symbol/!' '-cvalidate'", \
416         "htlatex.sh $$i 'html,word' 'symbol/!' '-cvalidate'", \
417         "/usr/share/tex4ht/htlatex $$i 'html,word' 'symbol/!' '-cvalidate'"],
418         rc_entry = [ r'\converter latex      wordhtml   "%%"    "needaux"' ])
419     if htmlconv.find('htlatex') >= 0:
420       addToRC(r'''\copier    wordhtml       "python -tt $$s/scripts/ext_copy.py -e html,png,css $$i $$o"''')
421     #
422     checkProg('an OpenOffice.org -> LaTeX converter', ['w2l -clean $$i'],
423         rc_entry = [ r'\converter sxw        latex      "%%"    ""' ])
424     #
425     checkProg('an OpenDocument -> LaTeX converter', ['w2l -clean $$i'],
426         rc_entry = [ r'\converter odt        latex      "%%"    ""' ])
427     # According to http://www.tug.org/applications/tex4ht/mn-commands.html
428     # the command mk4ht oolatex $$i has to be used as default,
429     # but as this would require to have Perl installed, in MiKTeX oolatex is
430     # directly available as application.
431     # On SuSE the scripts have a .sh suffix, and on debian they are in /usr/share/tex4ht/
432     # Both SuSE and debian have oolatex
433     checkProg('a LaTeX -> Open Document converter', [
434         'oolatex $$i', 'mk4ht oolatex $$i', 'oolatex.sh $$i', '/usr/share/tex4ht/oolatex $$i',
435         'htlatex $$i \'xhtml,ooffice\' \'ooffice/! -cmozhtf\' \'-coo\' \'-cvalidate\''],
436         rc_entry = [ r'\converter latex      odt        "%%"    "needaux"' ])
437     # On windows it is called latex2rt.exe
438     checkProg('a LaTeX -> RTF converter', ['latex2rtf -p -S -o $$o $$i', 'latex2rt -p -S -o $$o $$i'],
439         rc_entry = [ r'\converter latex      rtf        "%%"    "needaux"' ])
440     #
441     checkProg('a RTF -> HTML converter', ['unrtf --html  $$i > $$o'],
442         rc_entry = [ r'\converter rtf      html        "%%"     ""' ])
443     #
444     checkProg('a PS to PDF converter', ['ps2pdf13 $$i $$o'],
445         rc_entry = [ r'\converter ps         pdf        "%%"    ""' ])
446     #
447     checkProg('a PS to TXT converter', ['pstotext $$i > $$o'],
448         rc_entry = [ r'\converter ps         text2      "%%"    ""' ])
449     #
450     checkProg('a PS to TXT converter', ['ps2ascii $$i $$o'],
451         rc_entry = [ r'\converter ps         text3      "%%"    ""' ])
452     #
453     checkProg('a PS to EPS converter', ['ps2eps $$i'],
454         rc_entry = [ r'\converter ps         eps      "%%"      ""' ])
455     #
456     checkProg('a PDF to PS converter', ['pdf2ps $$i $$o', 'pdftops $$i $$o'],
457         rc_entry = [ r'\converter pdf         ps        "%%"    ""' ])
458     #
459     checkProg('a PDF to EPS converter', ['pdftops -eps -f 1 -l 1 $$i $$o'],
460         rc_entry = [ r'\converter pdf         eps        "%%"   ""' ])
461     #
462     checkProg('a DVI to TXT converter', ['catdvi $$i > $$o'],
463         rc_entry = [ r'\converter dvi        text4      "%%"    ""' ])
464     #
465     checkProg('a DVI to PS converter', ['dvips -o $$o $$i'],
466         rc_entry = [ r'\converter dvi        ps         "%%"    ""' ])
467     #
468     checkProg('a DVI to PDF converter', ['dvipdfmx -o $$o $$i', 'dvipdfm -o $$o $$i'],
469         rc_entry = [ r'\converter dvi        pdf3       "%%"    ""' ])
470     #
471     path, dvipng = checkProg('dvipng', ['dvipng'])
472     if dvipng == "dvipng":
473         addToRC(r'\converter lyxpreview png        "python -tt $$s/scripts/lyxpreview2bitmap.py"        ""')
474     else:
475         addToRC(r'\converter lyxpreview png        ""   ""')
476     #  
477     checkProg('a fax program', ['kdeprintfax $$i', 'ksendfax $$i'],
478         rc_entry = [ r'\converter ps         fax        "%%"    ""'])
479     #
480     checkProg('a FIG -> EPS/PPM converter', ['fig2dev'],
481         rc_entry = [
482             r'''\converter fig        eps        "fig2dev -L eps $$i $$o"       ""
483 \converter fig        ppm        "fig2dev -L ppm $$i $$o"       ""
484 \converter fig        png        "fig2dev -L png $$i $$o"       ""''',
485             ''])
486     #
487     checkProg('a TIFF -> PS converter', ['tiff2ps $$i > $$o'],
488         rc_entry = [ r'\converter tiff       eps        "%%"    ""', ''])
489     #
490     checkProg('a TGIF -> EPS/PPM converter', ['tgif'],
491         rc_entry = [
492             r'''\converter tgif       eps        "tgif -print -color -eps -stdout $$i > $$o"    ""
493 \converter tgif       png        "tgif -print -color -png -o $$d $$i"   ""
494 \converter tgif       pdf        "tgif -print -color -pdf -stdout $$i > $$o"    ""''',
495             ''])
496     #
497     checkProg('a WMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i'],
498         rc_entry = [ r'\converter wmf        eps        "%%"    ""'])
499     #
500     checkProg('an EMF -> EPS converter', ['metafile2eps $$i $$o', 'wmf2eps -o $$o $$i'],
501         rc_entry = [ r'\converter emf        eps        "%%"    ""'])
502     #
503     checkProg('an EPS -> PDF converter', ['epstopdf'],
504         rc_entry = [ r'\converter eps        pdf        "epstopdf --outfile=$$o $$i"    ""', ''])
505     #
506     # no agr -> pdf converter, since the pdf library used by gracebat is not
507     # free software and therefore not compiled in in many installations.
508     # Fortunately, this is not a big problem, because we will use epstopdf to
509     # convert from agr to pdf via eps without loss of quality.
510     checkProg('a Grace -> Image converter', ['gracebat'],
511         rc_entry = [
512             r'''\converter agr        eps        "gracebat -hardcopy -printfile $$o -hdevice EPS $$i 2>/dev/null"       ""
513 \converter agr        png        "gracebat -hardcopy -printfile $$o -hdevice PNG $$i 2>/dev/null"       ""
514 \converter agr        jpg        "gracebat -hardcopy -printfile $$o -hdevice JPEG $$i 2>/dev/null"      ""
515 \converter agr        ppm        "gracebat -hardcopy -printfile $$o -hdevice PNM $$i 2>/dev/null"       ""''',
516             ''])
517     #
518     checkProg('a Dot -> PDF converter', ['dot -Tpdf $$i -o $$o'],
519         rc_entry = [ r'\converter dot        pdf        "%%"    ""'])
520     #
521     checkProg('a Dia -> PNG converter', ['dia -e $$o -t png $$i'],
522         rc_entry = [ r'\converter dia        png        "%%"    ""'])
523     #
524     checkProg('a Dia -> EPS converter', ['dia -e $$o -t eps $$i'],
525         rc_entry = [ r'\converter dia        eps        "%%"    ""'])
526     #
527     #
528     path, lilypond = checkProg('a LilyPond -> EPS/PDF/PNG converter', ['lilypond'])
529     if (lilypond != ''):
530         version_string = cmdOutput("lilypond --version")
531         match = re.match('GNU LilyPond (\S+)', version_string)
532         if match:
533             version_number = match.groups()[0]
534             version = version_number.split('.')
535             if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 11):
536                 addToRC(r'''\converter lilypond   eps        "lilypond -dbackend=eps --ps $$i"  ""
537 \converter lilypond   png        "lilypond -dbackend=eps --png $$i"     ""''')
538                 addToRC(r'\converter lilypond   pdf        "lilypond -dbackend=eps --pdf $$i"   ""')
539                 print '+  found LilyPond version %s.' % version_number
540             elif int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 6):
541                 addToRC(r'''\converter lilypond   eps        "lilypond -b eps --ps $$i" ""
542 \converter lilypond   png        "lilypond -b eps --png $$i"    ""''')
543                 if int(version[0]) > 2 or (len(version) > 1 and int(version[0]) == 2 and int(version[1]) >= 9):
544                     addToRC(r'\converter lilypond   pdf        "lilypond -b eps --pdf $$i"      ""')
545                 logger.info('+  found LilyPond version %s.' % version_number)
546             else:
547                 logger.info('+  found LilyPond, but version %s is too old.' % version_number)
548         else:
549             logger.info('+  found LilyPond, but could not extract version number.')
550     #
551     checkProg('a Noteedit -> LilyPond converter', ['noteedit --export-lilypond $$i'],
552         rc_entry = [ r'\converter noteedit   lilypond   "%%"    ""', ''])
553     #
554     # FIXME: no rc_entry? comment it out
555     # checkProg('Image converter', ['convert $$i $$o'])
556     #
557     # Entries that do not need checkProg
558     addToRC(r'''\converter lyxpreview ppm        "python -tt $$s/scripts/lyxpreview2bitmap.py"  ""
559 \converter lyxpreview-platex ppm        "python -tt $$s/scripts/lyxpreview-platex2bitmap.py"    ""
560 \converter csv        lyx        "python -tt $$s/scripts/csv2lyx.py $$i $$o"    ""
561 \converter date       dateout    "python -tt $$s/scripts/date.py %d-%m-%Y > $$o"        ""
562 \converter docbook    docbook-xml "cp $$i $$o"  "xml"
563 \converter fen        asciichess "python -tt $$s/scripts/fen2ascii.py $$i $$o"  ""
564 \converter fig        pdftex     "python -tt $$s/scripts/fig2pdftex.py $$i $$o" ""
565 \converter fig        pstex      "python -tt $$s/scripts/fig2pstex.py $$i $$o"  ""
566 \converter lyx        lyx13x     "python -tt $$s/lyx2lyx/lyx2lyx -t 221 $$i > $$o"      ""
567 \converter lyx        lyx14x     "python -tt $$s/lyx2lyx/lyx2lyx -t 245 $$i > $$o"      ""
568 \converter lyx        lyx15x     "python -tt $$s/lyx2lyx/lyx2lyx -t 276 $$i > $$o"      ""
569 \converter lyx        lyx16x     "python -tt $$s/lyx2lyx/lyx2lyx -t 345 $$i > $$o"      ""
570 \converter lyx        clyx       "python -tt $$s/lyx2lyx/lyx2lyx -c big5 -t 245 $$i > $$o"      ""
571 \converter lyx        jlyx       "python -tt $$s/lyx2lyx/lyx2lyx -c euc_jp -t 245 $$i > $$o"    ""
572 \converter lyx        klyx       "python -tt $$s/lyx2lyx/lyx2lyx -c euc_kr -t 245 $$i > $$o"    ""
573 \converter clyx       lyx        "python -tt $$s/lyx2lyx/lyx2lyx -c big5 $$i > $$o"     ""
574 \converter jlyx       lyx        "python -tt $$s/lyx2lyx/lyx2lyx -c euc_jp $$i > $$o"   ""
575 \converter klyx       lyx        "python -tt $$s/lyx2lyx/lyx2lyx -c euc_kr $$i > $$o"   ""
576 ''')
577
578
579 def checkDocBook():
580     ''' Check docbook '''
581     path, DOCBOOK = checkProg('SGML-tools 2.x (DocBook), db2x scripts or xsltproc', ['sgmltools', 'db2dvi', 'xsltproc'],
582         rc_entry = [
583             r'''\converter docbook    dvi        "sgmltools -b dvi $$i" ""
584 \converter docbook    html       "sgmltools -b html $$i"        ""''',
585             r'''\converter docbook    dvi        "db2dvi $$i"   ""
586 \converter docbook    html       "db2html $$i"  ""''',
587             r'''\converter docbook    dvi        ""     ""
588 \converter docbook    html       "" ""''',
589             r'''\converter docbook    dvi        ""     ""
590 \converter docbook    html       ""     ""'''])
591     #
592     if DOCBOOK != '':
593         return ('yes', 'true', '\\def\\hasdocbook{yes}')
594     else:
595         return ('no', 'false', '')
596
597
598 def checkOtherEntries():
599     ''' entries other than Format and Converter '''
600     checkProg('ChkTeX', ['chktex -n1 -n3 -n6 -n9 -n22 -n25 -n30 -n38'],
601         rc_entry = [ r'\chktex_command "%%"' ])
602     checkProg('BibTeX', ['bibtex'],
603         rc_entry = [ r'\bibtex_command "%%"' ])
604     checkProg('JBibTeX, the Japanese BibTeX', ['jbibtex', 'bibtex'],
605         rc_entry = [ r'\jbibtex_command "%%"' ])
606     checkProg('an index processor', ['texindy', 'makeindex -c -q'],
607         rc_entry = [ r'\index_command "%%"' ])
608     checkProg('an index processor appropriate to Japanese', ['mendex -c -q', 'makeindex -c -q'],
609         rc_entry = [ r'\jindex_command "%%"' ])
610     checkProg('the splitindex processor', ['splitindex.pl', 'java splitindex', 'splitindex'],
611         rc_entry = [ r'\splitindex_command "%%"' ])
612     checkProg('a nomenclature processor', ['makeindex'],
613         rc_entry = [ r'\nomencl_command "makeindex -s nomencl.ist"' ])
614     ## FIXME: OCTAVE is not used anywhere
615     # path, OCTAVE = checkProg('Octave', ['octave'])
616     ## FIXME: MAPLE is not used anywhere
617     # path, MAPLE = checkProg('Maple', ['maple'])
618     checkProg('a spool command', ['lp', 'lpr'],
619         rc_entry = [
620             r'''\print_spool_printerprefix "-d "
621 \print_spool_command "lp"''',
622             r'''\print_spool_printerprefix "-P",
623 \print_spool_command "lpr"''',
624             ''])
625     # Add the rest of the entries (no checkProg is required)
626     addToRC(r'''\copier    fig        "python -tt $$s/scripts/fig_copy.py $$i $$o"
627 \copier    pstex      "python -tt $$s/scripts/tex_copy.py $$i $$o $$l"
628 \copier    pdftex     "python -tt $$s/scripts/tex_copy.py $$i $$o $$l"
629 \copier    program    "python -tt $$s/scripts/ext_copy.py $$i $$o"
630 ''')
631
632
633 def processLayoutFile(file, bool_docbook):
634     ''' process layout file and get a line of result
635         
636         Declare lines look like this: (article.layout, scrbook.layout, svjog.layout)
637         
638         \DeclareLaTeXClass{article}
639         \DeclareLaTeXClass[scrbook]{book (koma-script)}
640         \DeclareLaTeXClass[svjour,svjog.clo]{article (Springer - svjour/jog)}
641
642         we expect output:
643         
644         "article" "article" "article" "false"
645         "scrbook" "scrbook" "book (koma-script)" "false"
646         "svjog" "svjour" "article (Springer - svjour/jog)" "false"
647     '''
648     classname = file.split(os.sep)[-1].split('.')[0]
649     # return ('LaTeX', '[a,b]', 'a', ',b,c', 'article') for \DeclareLaTeXClass[a,b,c]{article}
650     p = re.compile(r'\Declare(LaTeX|DocBook)Class\s*(\[([^,]*)(,.*)*\])*\s*{(.*)}')
651     for line in open(file).readlines():
652         res = p.search(line)
653         if res != None:
654             (classtype, optAll, opt, opt1, desc) = res.groups()
655             avai = {'LaTeX':'false', 'DocBook':bool_docbook}[classtype]
656             if opt == None:
657                 opt = classname
658             return '"%s" "%s" "%s" "%s"\n' % (classname, opt, desc, avai)
659     logger.warning("Layout file " + file + " has no \DeclareXXClass line. ")
660     return ""
661
662
663 def checkLatexConfig(check_config, bool_docbook):
664     ''' Explore the LaTeX configuration 
665         Return None (will be passed to sys.exit()) for success.
666     '''
667     msg = 'checking LaTeX configuration... '
668     # if --without-latex-config is forced, or if there is no previous 
669     # version of textclass.lst, re-generate a default file.
670     if not os.path.isfile('textclass.lst') or not check_config:
671         # remove the files only if we want to regenerate
672         removeFiles(['textclass.lst', 'packages.lst'])
673         #
674         # Then, generate a default textclass.lst. In case configure.py
675         # fails, we still have something to start lyx.
676         logger.info(msg + ' default values')
677         logger.info('+checking list of textclasses... ')
678         tx = open('textclass.lst', 'w')
679         tx.write('''
680 # This file declares layouts and their associated definition files
681 # (include dir. relative to the place where this file is).
682 # It contains only default values, since chkconfig.ltx could not be run
683 # for some reason. Run ./configure.py if you need to update it after a
684 # configuration change.
685 ''')
686         # build the list of available layout files and convert it to commands
687         # for chkconfig.ltx
688         foundClasses = []
689         for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
690             glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
691             # valid file?
692             if not os.path.isfile(file): 
693                 continue
694             # get stuff between /xxxx.layout .
695             classname = file.split(os.sep)[-1].split('.')[0]
696             #  tr ' -' '__'`
697             cleanclass = classname.replace(' ', '_')
698             cleanclass = cleanclass.replace('-', '_')
699             # make sure the same class is not considered twice
700             if foundClasses.count(cleanclass) == 0: # not found before
701                 foundClasses.append(cleanclass)
702                 retval = processLayoutFile(file, bool_docbook)
703                 if retval != "":
704                     tx.write(retval)
705         tx.close()
706         logger.info('\tdone')
707     if not check_config:
708         return None
709     # the following will generate textclass.lst.tmp, and packages.lst.tmp
710     else:
711         logger.info(msg + '\tauto')
712         removeFiles(['wrap_chkconfig.ltx', 'chkconfig.vars', \
713             'chkconfig.classes', 'chklayouts.tex'])
714         rmcopy = False
715         if not os.path.isfile( 'chkconfig.ltx' ):
716             shutil.copyfile( os.path.join(srcdir, 'chkconfig.ltx'), 'chkconfig.ltx' )
717             rmcopy = True
718         writeToFile('wrap_chkconfig.ltx', '%s\n\\input{chkconfig.ltx}\n' % docbook_cmd)
719         # Construct the list of classes to test for.
720         # build the list of available layout files and convert it to commands
721         # for chkconfig.ltx
722         p1 = re.compile(r'\Declare(LaTeX|DocBook)Class')
723         testclasses = list()
724         for file in glob.glob( os.path.join('layouts', '*.layout') ) + \
725             glob.glob( os.path.join(srcdir, 'layouts', '*.layout' ) ) :
726             if not os.path.isfile(file):
727                 continue
728             classname = file.split(os.sep)[-1].split('.')[0]
729             for line in open(file).readlines():
730                 if p1.search(line) == None:
731                     continue
732                 if line[0] != '#':
733                     logger.error("Wrong input layout file with line '" + line)
734                     sys.exit(3)
735                 testclasses.append("\\TestDocClass{%s}{%s}" % (classname, line[1:].strip()))
736                 break
737         testclasses.sort()
738         cl = open('chklayouts.tex', 'w')
739         for line in testclasses:
740             cl.write(line + '\n')
741         cl.close()
742         #
743         # we have chklayouts.tex, then process it
744         fout = os.popen(LATEX + ' wrap_chkconfig.ltx')
745         while True:
746             line = fout.readline()
747             if not line:
748                 break;
749             if re.match('^\+', line):
750                 logger.info(line.strip())
751         # if the command succeeds, None will be returned
752         ret = fout.close()
753         #
754         # currently, values in chhkconfig are only used to set
755         # \font_encoding
756         values = {}
757         for line in open('chkconfig.vars').readlines():
758             key, val = re.sub('-', '_', line).split('=')
759             val = val.strip()
760             values[key] = val.strip("'")
761         # chk_fontenc may not exist 
762         try:
763             addToRC(r'\font_encoding "%s"' % values["chk_fontenc"])
764         except:
765             pass
766         if rmcopy:   # remove the copied file
767             removeFiles( [ 'chkconfig.ltx' ] )
768         # if configure successed, move textclass.lst.tmp to textclass.lst
769         # and packages.lst.tmp to packages.lst
770         if os.path.isfile('textclass.lst.tmp') and len(open('textclass.lst.tmp').read()) > 0 \
771             and os.path.isfile('packages.lst.tmp') and len(open('packages.lst.tmp').read()) > 0:
772             shutil.move('textclass.lst.tmp', 'textclass.lst')
773             shutil.move('packages.lst.tmp', 'packages.lst')
774         return ret
775
776
777 def checkModulesConfig():
778   removeFiles(['lyxmodules.lst'])
779
780   logger.info('+checking list of modules... ')
781   tx = open('lyxmodules.lst', 'w')
782   tx.write('''## This file declares modules and their associated definition files.
783 ## It has been automatically generated by configure
784 ## Use "Options/Reconfigure" if you need to update it after a
785 ## configuration change. 
786 ''')
787   # build the list of available modules
788   foundClasses = []
789   for file in glob.glob( os.path.join('layouts', '*.module') ) + \
790       glob.glob( os.path.join(srcdir, 'layouts', '*.module' ) ) :
791       # valid file?
792       logger.info(file)
793       if not os.path.isfile(file): 
794           continue
795       retval = processModuleFile(file, bool_docbook)
796       if retval != "":
797           tx.write(retval)
798   tx.close()
799   logger.info('\tdone')
800
801
802 def processModuleFile(file, bool_docbook):
803     ''' process module file and get a line of result
804
805         The top of a module file should look like this:
806           #\DeclareLyXModule[LaTeX Packages]{ModuleName}
807           #BeginDescription
808           #...body of description...
809           #EndDescription
810           #Requires: [list of required modules]
811           #Excludes: [list of excluded modules]
812         The last two lines are optional
813         We expect output:
814           "ModuleName" "filename" "Description" "Packages" "Requires" "Excludes"
815     '''
816     p = re.compile(r'\DeclareLyXModule\s*(?:\[([^]]*?)\])?{(.*)}')
817     r = re.compile(r'#+\s*Requires: (.*)')
818     x = re.compile(r'#+\s*Excludes: (.*)')
819     b = re.compile(r'#+\s*DescriptionBegin\s*$')
820     e = re.compile(r'#+\s*DescriptionEnd\s*$')
821
822     modname = desc = pkgs = req = excl = ""
823     readingDescription = False
824     descLines = []
825     filename = file.split(os.sep)[-1]
826     filename = filename[:-7]
827
828     for line in open(file).readlines():
829       if readingDescription:
830         res = e.search(line)
831         if res != None:
832           readingDescription = False
833           desc = " ".join(descLines)
834           continue
835         descLines.append(line[1:].strip())
836         continue
837       res = b.search(line)
838       if res != None:
839         readingDescription = True
840         continue
841       res = p.search(line)
842       if res != None:
843           (pkgs, modname) = res.groups()
844           if pkgs == None:
845             pkgs = ""
846           else:
847             tmp = [s.strip() for s in pkgs.split(",")]
848             pkgs = ",".join(tmp)
849           continue
850       res = r.search(line)
851       if res != None:
852         req = res.group(1)
853         tmp = [s.strip() for s in req.split("|")]
854         req = "|".join(tmp)
855         continue
856       res = x.search(line)
857       if res != None:
858         excl = res.group(1)
859         tmp = [s.strip() for s in excl.split("|")]
860         excl = "|".join(tmp)
861         continue
862     if modname != "":
863         return '"%s" "%s" "%s" "%s" "%s" "%s"\n' % (modname, filename, desc, pkgs, req, excl)
864     logger.warning("Module file without \DeclareLyXModule line. ")
865     return ""
866
867
868 def checkTeXAllowSpaces():
869     ''' Let's check whether spaces are allowed in TeX file names '''
870     tex_allows_spaces = 'false'
871     if lyx_check_config:
872         msg = "Checking whether TeX allows spaces in file names... "
873         writeToFile('a b.tex', r'\message{working^^J}' )
874         if os.name == 'nt':
875             latex_out = cmdOutput(LATEX + r""" "\nonstopmode\input{\"a b\"}" """)
876         else:
877             latex_out = cmdOutput(LATEX + r""" '\nonstopmode\input{"a b"}' """)
878         if 'working' in latex_out:
879             logger.info(msg + 'yes')
880             tex_allows_spaces = 'true'
881         else:
882             logger.info(msg + 'no')
883             tex_allows_spaces = 'false'
884         addToRC(r'\tex_allows_spaces ' + tex_allows_spaces)
885         removeFiles( [ 'a b.tex', 'a b.log', 'texput.log' ])
886
887
888 def removeTempFiles():
889     # Final clean-up
890     if not lyx_keep_temps:
891         removeFiles(['chkconfig.vars',  \
892             'wrap_chkconfig.ltx', 'wrap_chkconfig.log', \
893             'chklayouts.tex', 'missfont.log', 
894             'chklatex.ltx', 'chklatex.log'])
895
896
897 if __name__ == '__main__':
898     lyx_check_config = True
899     outfile = 'lyxrc.defaults'
900     rc_entries = ''
901     lyx_keep_temps = False
902     version_suffix = ''
903     ## Parse the command line
904     for op in sys.argv[1:]:   # default shell/for list is $*, the options
905         if op in [ '-help', '--help', '-h' ]:
906             print '''Usage: configure [options]
907 Options:
908     --help                   show this help lines
909     --keep-temps             keep temporary files (for debug. purposes)
910     --without-latex-config   do not run LaTeX to determine configuration
911     --with-version-suffix=suffix suffix of binary installed files
912 '''
913             sys.exit(0)
914         elif op == '--without-latex-config':
915             lyx_check_config = False
916         elif op == '--keep-temps':
917             lyx_keep_temps = True
918         elif op[0:22] == '--with-version-suffix=':  # never mind if op is not long enough
919             version_suffix = op[22:]
920         else:
921             print "Unknown option", op
922             sys.exit(1)
923     #
924     # check if we run from the right directory
925     srcdir = os.path.dirname(sys.argv[0])
926     if srcdir == '':
927         srcdir = '.'
928     if not os.path.isfile( os.path.join(srcdir, 'chkconfig.ltx') ):
929         logger.error("configure: error: cannot find chkconfig.ltx script")
930         sys.exit(1)
931     setEnviron()
932     createDirectories()
933     windows_style_tex_paths = checkTeXPaths()
934     dtl_tools = checkDTLtools()
935     ## Write the first part of outfile
936     writeToFile(outfile, '''# This file has been automatically generated by LyX' lib/configure.py
937 # script. It contains default settings that have been determined by
938 # examining your system. PLEASE DO NOT MODIFY ANYTHING HERE! If you
939 # want to customize LyX, use LyX' Preferences dialog or modify directly 
940 # the "preferences" file instead. Any setting in that file will
941 # override the values given here.
942 ''')
943     # check latex
944     LATEX = checkLatex(dtl_tools)
945     checkFormatEntries(dtl_tools)
946     checkConverterEntries()
947     (chk_docbook, bool_docbook, docbook_cmd) = checkDocBook()
948     checkTeXAllowSpaces()
949     if windows_style_tex_paths != '':
950         addToRC(r'\tex_expects_windows_paths %s' % windows_style_tex_paths)
951     checkOtherEntries()
952     # --without-latex-config can disable lyx_check_config
953     ret = checkLatexConfig(lyx_check_config and LATEX != '', bool_docbook)
954     checkModulesConfig() #lyx_check_config and LATEX != '')
955     removeTempFiles()
956     # The return error code can be 256. Because most systems expect an error code
957     # in the range 0-127, 256 can be interpretted as 'success'. Because we expect
958     # a None for success, 'ret is not None' is used to exit.
959     sys.exit(ret is not None)