Attachment 'doxygen.py'

Download

   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             if key == "TAGFILES" and data.has_key(key):
  67                append_data( data, key, False, "=" )
  68                new_data=False
  69             else:
  70                data[key] = list()
  71          else:
  72             append_data( data, key, new_data, token )
  73             new_data = True
  74 
  75       last_token = token
  76       token = lex.get_token()
  77 
  78       if last_token == '\\' and token != '\n':
  79          new_data = False
  80          append_data( data, key, new_data, '\\' )
  81 
  82    # compress lists of len 1 into single strings
  83    for (k, v) in data.items():
  84       if len(v) == 0:
  85          data.pop(k)
  86 
  87       # items in the following list will be kept as lists and not converted to strings
  88       if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS", "TAGFILES"]:
  89          continue
  90 
  91       if len(v) == 1:
  92          data[k] = v[0]
  93 
  94    return data
  95 
  96 def DoxySourceScan(node, env, path):
  97    """
  98    Doxygen Doxyfile source scanner.  This should scan the Doxygen file and add
  99    any files used to generate docs to the list of source files.
 100    """
 101    default_file_patterns = [
 102       '*.c', '*.cc', '*.cxx', '*.cpp', '*.c++', '*.java', '*.ii', '*.ixx',
 103       '*.ipp', '*.i++', '*.inl', '*.h', '*.hh ', '*.hxx', '*.hpp', '*.h++',
 104       '*.idl', '*.odl', '*.cs', '*.php', '*.php3', '*.inc', '*.m', '*.mm',
 105       '*.py',
 106    ]
 107 
 108    default_exclude_patterns = [
 109       '*~',
 110    ]
 111 
 112    sources = []
 113 
 114    data = DoxyfileParse(node.get_contents())
 115 
 116    if data.get("RECURSIVE", "NO") == "YES":
 117       recursive = True
 118    else:
 119       recursive = False
 120 
 121    file_patterns = data.get("FILE_PATTERNS", default_file_patterns)
 122    exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns)
 123 
 124    # We're running in the top-level directory, but the doxygen
 125    # configuration file is in the same directory as node; this means
 126    # that relative pathnames in node must be adjusted before they can
 127    # go onto the sources list
 128    conf_dir = os.path.dirname(str(node))
 129    
 130    for node in data.get("INPUT", []):
 131       if not os.path.isabs(node):
 132          node = os.path.join(conf_dir, node)
 133       if os.path.isfile(node):
 134          sources.append(node)
 135       elif os.path.isdir(node):
 136          if recursive:
 137             for root, dirs, files in os.walk(node):
 138                for f in files:
 139                   filename = os.path.join(root, f)
 140 
 141                   pattern_check = reduce(lambda x, y: x or bool(fnmatch(filename, y)), file_patterns, False)
 142                   exclude_check = reduce(lambda x, y: x and fnmatch(filename, y), exclude_patterns, True)
 143 
 144                   if pattern_check and not exclude_check:
 145                      sources.append(filename)
 146          else:
 147             for pattern in file_patterns:
 148                sources.extend(glob.glob("/".join([node, pattern])))
 149 
 150    # Add tagfiles to the list of source files:
 151    for node in data.get("TAGFILES", []):
 152       file = node.split("=")[0]
 153       if not os.path.isabs(file):
 154          file = os.path.join(conf_dir, file)
 155       sources.append(file)
 156    
 157    # Add additional files to the list of source files:
 158    def append_additional_source(option):
 159       file = data.get(option, "")
 160       if file != "":
 161          if not os.path.isabs(file):
 162             file = os.path.join(conf_dir, file)
 163          if os.path.isfile(file):
 164             sources.append(file)
 165 
 166    append_additional_source("HTML_STYLESHEET")
 167    append_additional_source("HTML_HEADER")
 168    append_additional_source("HTML_FOOTER")
 169 
 170    sources = map( lambda path: env.File(path), sources )
 171    return sources
 172 
 173 
 174 def DoxySourceScanCheck(node, env):
 175    """Check if we should scan this file"""
 176    return os.path.isfile(node.path)
 177 
 178 def DoxyEmitter(source, target, env):
 179    """Doxygen Doxyfile emitter"""
 180    # possible output formats and their default values and output locations
 181    output_formats = {
 182       "HTML": ("YES", "html"),
 183       "LATEX": ("YES", "latex"),
 184       "RTF": ("NO", "rtf"),
 185       "MAN": ("YES", "man"),
 186       "XML": ("NO", "xml"),
 187    }
 188 
 189    data = DoxyfileParse(source[0].get_contents())
 190 
 191    targets = []
 192    out_dir = data.get("OUTPUT_DIRECTORY", ".")
 193    if not os.path.isabs(out_dir):
 194       conf_dir = os.path.dirname(str(source[0]))
 195       out_dir = os.path.join(conf_dir, out_dir)
 196 
 197    # add our output locations
 198    for (k, v) in output_formats.items():
 199       if data.get("GENERATE_" + k, v[0]) == "YES":
 200          targets.append(env.Dir( os.path.join(out_dir, data.get(k + "_OUTPUT", v[1]))) )
 201 
 202    # add the tag file if neccessary:
 203    tagfile = data.get("GENERATE_TAGFILE", "")
 204    if tagfile != "":
 205       if not os.path.isabs(tagfile):
 206          conf_dir = os.path.dirname(str(source[0]))
 207          tagfile = os.path.join(conf_dir, tagfile)
 208       targets.append(env.File(tagfile))
 209 
 210    # don't clobber targets
 211    for node in targets:
 212       env.Precious(node)
 213 
 214    # set up cleaning stuff
 215    for node in targets:
 216       env.Clean(node, node)
 217 
 218    return (targets, source)
 219 
 220 def generate(env):
 221    """
 222    Add builders and construction variables for the
 223    Doxygen tool.  This is currently for Doxygen 1.4.6.
 224    """
 225    doxyfile_scanner = env.Scanner(
 226       DoxySourceScan,
 227       "DoxySourceScan",
 228       scan_check = DoxySourceScanCheck,
 229    )
 230 
 231    import SCons.Builder
 232    doxyfile_builder = SCons.Builder.Builder(
 233       action = "cd ${SOURCE.dir}  &&  ${DOXYGEN} ${SOURCE.file}",
 234       emitter = DoxyEmitter,
 235       target_factory = env.fs.Entry,
 236       single_source = True,
 237       source_scanner =  doxyfile_scanner,
 238    )
 239 
 240    env.Append(BUILDERS = {
 241       'Doxygen': doxyfile_builder,
 242    })
 243 
 244    env.AppendUnique(
 245       DOXYGEN = 'doxygen',
 246    )
 247 
 248 def exists(env):
 249    """
 250    Make sure doxygen exists.
 251    """
 252    return env.Detect("doxygen")

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.