root/trunk/libffado/admin/doxygen.py

Revision 605, 5.9 kB (checked in by arnonym, 13 years ago)

Docs are back!

Line 
1 # vim: set et sw=3 tw=0 fo=awqorc ft=python:
2 #
3 # Astxx, the Asterisk C++ API and Utility Library.
4 # Copyright (C) 2005, 2006  Matthew A. Nicholson
5 # Copyright (C) 2006  Tim Blechmann
6 #
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License version 2.1 as published by the Free Software Foundation.
10 #
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 import os
21 import os.path
22 import glob
23 from fnmatch import fnmatch
24
25 def DoxyfileParse(file_contents):
26    """
27    Parse a Doxygen source file and return a dictionary of all the values.
28    Values will be strings and lists of strings.
29    """
30    data = {}
31
32    import shlex
33    lex = shlex.shlex(instream = file_contents, posix = True)
34    lex.wordchars += "*+./-:"
35    lex.whitespace = lex.whitespace.replace("\n", "")
36    lex.escape = ""
37
38    lineno = lex.lineno
39    token = lex.get_token()
40    key = token   # the first token should be a key
41    last_token = ""
42    key_token = False
43    next_key = False
44    new_data = True
45
46    def append_data(data, key, new_data, token):
47       if new_data or len(data[key]) == 0:
48          data[key].append(token)
49       else:
50          data[key][-1] += token
51
52    while token:
53       if token in ['\n']:
54          if last_token not in ['\\']:
55             key_token = True
56       elif token in ['\\']:
57          pass
58       elif key_token:
59          key = token
60          key_token = False
61       else:
62          if token == "+=":
63             if not data.has_key(key):
64                data[key] = list()
65          elif token == "=":
66             data[key] = list()
67          else:
68             append_data( data, key, new_data, token )
69             new_data = True
70
71       last_token = token
72       token = lex.get_token()
73
74       if last_token == '\\' and token != '\n':
75          new_data = False
76          append_data( data, key, new_data, '\\' )
77
78    # compress lists of len 1 into single strings
79    for (k, v) in data.items():
80       if len(v) == 0:
81          data.pop(k)
82
83       # items in the following list will be kept as lists and not converted to strings
84       if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS"]:
85          continue
86
87       if len(v) == 1:
88          data[k] = v[0]
89
90    return data
91
92 def DoxySourceScan(node, env, path):
93    """
94    Doxygen Doxyfile source scanner.  This should scan the Doxygen file and add
95    any files used to generate docs to the list of source files.
96    """
97    default_file_patterns = [
98       '*.c', '*.cc', '*.cxx', '*.cpp', '*.c++', '*.java', '*.ii', '*.ixx',
99       '*.ipp', '*.i++', '*.inl', '*.h', '*.hh ', '*.hxx', '*.hpp', '*.h++',
100       '*.idl', '*.odl', '*.cs', '*.php', '*.php3', '*.inc', '*.m', '*.mm',
101       '*.py',
102    ]
103
104    default_exclude_patterns = [
105       '*~',
106    ]
107
108    sources = []
109
110    data = DoxyfileParse(node.get_contents())
111
112    if data.get("RECURSIVE", "NO") == "YES":
113       recursive = True
114    else:
115       recursive = False
116
117    file_patterns = data.get("FILE_PATTERNS", default_file_patterns)
118    exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns)
119
120    for node in data.get("INPUT", []):
121       if os.path.isfile(node):
122          sources.append(node)
123       elif os.path.isdir(node):
124          if recursive:
125             for root, dirs, files in os.walk(node):
126                for f in files:
127                   filename = os.path.join(root, f)
128
129                   pattern_check = reduce(lambda x, y: x or bool(fnmatch(filename, y)), file_patterns, False)
130                   exclude_check = reduce(lambda x, y: x and fnmatch(filename, y), exclude_patterns, True)
131
132                   if pattern_check and not exclude_check:
133                      sources.append(filename)
134          else:
135             for pattern in file_patterns:
136                sources.extend(glob.glob("/".join([node, pattern])))
137
138    sources = map( lambda path: env.File(path), sources )
139    return sources
140
141
142 def DoxySourceScanCheck(node, env):
143    """Check if we should scan this file"""
144    return os.path.isfile(node.path)
145
146 def DoxyEmitter(source, target, env):
147    """Doxygen Doxyfile emitter"""
148    # possible output formats and their default values and output locations
149    output_formats = {
150       "HTML": ("YES", "html"),
151       "LATEX": ("YES", "latex"),
152       "RTF": ("NO", "rtf"),
153       "MAN": ("YES", "man"),
154       "XML": ("NO", "xml"),
155    }
156
157    data = DoxyfileParse(source[0].get_contents())
158
159    targets = []
160    out_dir = data.get("OUTPUT_DIRECTORY", ".")
161
162    # add our output locations
163    for (k, v) in output_formats.items():
164       if data.get("GENERATE_" + k, v[0]) == "YES":
165          targets.append(env.Dir( os.path.join(out_dir, data.get(k + "_OUTPUT", v[1]))) )
166
167    # don't clobber targets
168    for node in targets:
169       env.Precious(node)
170
171    # set up cleaning stuff
172    for node in targets:
173       env.Clean(node, node)
174
175    return (targets, source)
176
177 def generate(env):
178    """
179    Add builders and construction variables for the
180    Doxygen tool.  This is currently for Doxygen 1.4.6.
181    """
182    doxyfile_scanner = env.Scanner(
183       DoxySourceScan,
184       "DoxySourceScan",
185       scan_check = DoxySourceScanCheck,
186    )
187
188    import SCons.Builder
189    doxyfile_builder = SCons.Builder.Builder(
190       action = "cd ${SOURCE.dir}  &&  ${DOXYGEN} ${SOURCE.file}",
191       emitter = DoxyEmitter,
192       target_factory = env.fs.Entry,
193       single_source = True,
194       source_scanner =  doxyfile_scanner,
195    )
196
197    env.Append(BUILDERS = {
198       'Doxygen': doxyfile_builder,
199    })
200
201    env.AppendUnique(
202       DOXYGEN = 'doxygen',
203    )
204
205 def exists(env):
206    """
207    Make sure doxygen exists.
208    """
209    return env.Detect("doxygen")
Note: See TracBrowser for help on using the browser.