root/trunk/libffado/admin/doxygen.py

Revision 864, 6.6 kB (checked in by ppalmers, 16 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

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