12eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerimport os 22eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerimport os.path 32eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerfrom fnmatch import fnmatch 42eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerimport targz 52eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger 62eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger##def DoxyfileParse(file_contents): 72eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## """ 82eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## Parse a Doxygen source file and return a dictionary of all the values. 92eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## Values will be strings and lists of strings. 102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## """ 112eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## data = {} 122eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 132eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## import shlex 142eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## lex = shlex.shlex(instream = file_contents, posix = True) 152eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## lex.wordchars += "*+./-:" 162eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## lex.whitespace = lex.whitespace.replace("\n", "") 172eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## lex.escape = "" 182eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 192eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## lineno = lex.lineno 202eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## last_backslash_lineno = lineno 212eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## token = lex.get_token() 222eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## key = token # the first token should be a key 232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## last_token = "" 242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## key_token = False 252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## next_key = False 262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## new_data = True 272eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 282eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## def append_data(data, key, new_data, token): 292eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if new_data or len(data[key]) == 0: 302eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## data[key].append(token) 312eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## else: 322eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## data[key][-1] += token 332eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 342eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## while token: 352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if token in ['\n']: 362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if last_token not in ['\\']: 372eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## key_token = True 382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## elif token in ['\\']: 392eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## pass 402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## elif key_token: 412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## key = token 422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## key_token = False 432eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## else: 442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if token == "+=": 452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if not data.has_key(key): 462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## data[key] = list() 472eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## elif token == "=": 482eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## data[key] = list() 492eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## else: 502eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## append_data( data, key, new_data, token ) 512eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## new_data = True 522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## last_token = token 542eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## token = lex.get_token() 552eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if last_token == '\\' and token != '\n': 572eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## new_data = False 582eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## append_data( data, key, new_data, '\\' ) 592eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## # compress lists of len 1 into single strings 612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## for (k, v) in data.items(): 622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if len(v) == 0: 632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## data.pop(k) 642eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## # items in the following list will be kept as lists and not converted to strings 662eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS"]: 672eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## continue 682eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if len(v) == 1: 702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## data[k] = v[0] 712eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## return data 732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 742eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger##def DoxySourceScan(node, env, path): 752eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## """ 762eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## Doxygen Doxyfile source scanner. This should scan the Doxygen file and add 772eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## any files used to generate docs to the list of source files. 782eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## """ 792eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## default_file_patterns = [ 802eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## '*.c', '*.cc', '*.cxx', '*.cpp', '*.c++', '*.java', '*.ii', '*.ixx', 812eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## '*.ipp', '*.i++', '*.inl', '*.h', '*.hh ', '*.hxx', '*.hpp', '*.h++', 822eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## '*.idl', '*.odl', '*.cs', '*.php', '*.php3', '*.inc', '*.m', '*.mm', 832eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## '*.py', 842eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## ] 852eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 862eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## default_exclude_patterns = [ 872eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## '*~', 882eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## ] 892eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 902eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## sources = [] 912eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 922eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## data = DoxyfileParse(node.get_contents()) 932eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 942eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if data.get("RECURSIVE", "NO") == "YES": 952eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## recursive = True 962eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## else: 972eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## recursive = False 982eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 992eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## file_patterns = data.get("FILE_PATTERNS", default_file_patterns) 1002eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns) 1012eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1022eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## for node in data.get("INPUT", []): 1032eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if os.path.isfile(node): 1042eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## sources.add(node) 1052eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## elif os.path.isdir(node): 1062eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if recursive: 1072eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## for root, dirs, files in os.walk(node): 1082eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## for f in files: 1092eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## filename = os.path.join(root, f) 1102eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1112eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## pattern_check = reduce(lambda x, y: x or bool(fnmatch(filename, y)), file_patterns, False) 1122eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## exclude_check = reduce(lambda x, y: x and fnmatch(filename, y), exclude_patterns, True) 1132eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1142eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if pattern_check and not exclude_check: 1152eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## sources.append(filename) 1162eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## else: 1172eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## for pattern in file_patterns: 1182eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## sources.extend(glob.glob("/".join([node, pattern]))) 1192eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## sources = map( lambda path: env.File(path), sources ) 1202eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## return sources 1212eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1222eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1232eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger##def DoxySourceScanCheck(node, env): 1242eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## """Check if we should scan this file""" 1252eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## return os.path.isfile(node.path) 1262eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger 1272eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerdef srcDistEmitter(source, target, env): 1282eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## """Doxygen Doxyfile emitter""" 1292eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## # possible output formats and their default values and output locations 1302eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## output_formats = { 1312eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## "HTML": ("YES", "html"), 1322eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## "LATEX": ("YES", "latex"), 1332eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## "RTF": ("NO", "rtf"), 1342eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## "MAN": ("YES", "man"), 1352eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## "XML": ("NO", "xml"), 1362eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## } 1372eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1382eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## data = DoxyfileParse(source[0].get_contents()) 1392eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1402eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## targets = [] 1412eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## out_dir = data.get("OUTPUT_DIRECTORY", ".") 1422eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1432eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## # add our output locations 1442eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## for (k, v) in output_formats.items(): 1452eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## if data.get("GENERATE_" + k, v[0]) == "YES": 1462eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## targets.append(env.Dir( os.path.join(out_dir, data.get(k + "_OUTPUT", v[1]))) ) 1472eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1482eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## # don't clobber targets 1492eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## for node in targets: 1502eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## env.Precious(node) 1512eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1522eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## # set up cleaning stuff 1532eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## for node in targets: 1542eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## env.Clean(node, node) 1552eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## 1562eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## return (targets, source) 1572eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger return (target,source) 1582eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger 1592eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerdef generate(env): 1602eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger """ 1612eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger Add builders and construction variables for the 1622eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger SrcDist tool. 1632eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger """ 1642eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## doxyfile_scanner = env.Scanner( 1652eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## DoxySourceScan, 1662eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## "DoxySourceScan", 1672eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## scan_check = DoxySourceScanCheck, 1682eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger## ) 1692eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger 1702eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger if targz.exists(env): 1712eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger srcdist_builder = targz.makeBuilder( srcDistEmitter ) 1722eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger 1732eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger env['BUILDERS']['SrcDist'] = srcdist_builder 1742eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger 1752eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenbergerdef exists(env): 1762eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger """ 1772eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger Make sure srcdist exists. 1782eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger """ 1792eb3b4d7ea1a3cbb0f8775de3b6d92c0a6152f9fDerek Sollenberger return targz.exists(env) 180