Synopsis - Cross-Reference
File: /scripts/synopsis1#!/usr/bin/env python 2# 3# Copyright (C) 2003 Stefan Seefeld 4# All rights reserved. 5# Licensed to the public under the terms of the GNU LGPL (>= 2), 6# see the file COPYING for details. 7# 8 9from Synopsis import config 10from Synopsis.getoptions import get_options 11from Synopsis import IR 12from Synopsis.Processor import Processor, Composite, Error 13from Synopsis.Processors import * 14 15import sys, os, os.path, getopt 16 17def error(msg): 18 """Write an error message and exit.""" 19 sys.stderr.write('Error: %s\n'%msg) 20 sys.exit(-1) 21 22def __import__(name, verbose): 23 """Import a named processor. Instead of returning the module, this 24 reimplementation returns the processor itself. Exits on error.""" 25 26 from Synopsis.import_processor import import_processor 27 try: 28 return import_processor(name) 29 30 except ImportError, msg: 31 if verbose: 32 print 'Unable to import %s'%name 33 print 'Reason :', msg 34 else: 35 print 'Error : no processor \'%s\''%'.'.join(name.split('.')[-2:]) 36 sys.exit(-1) 37 38def usage(): 39 """Print a little usage text""" 40 41 print 'Usage : %s [options] <input files>'%'synopsis' 42 print """ 43List of options: 44 -h, --help Display usage summary. 45 -V, --version Display version information. 46 -v --verbose Operate verbosely. 47 -d --debug Operate in debug mode. 48 -o <file>, --output=<file> Write output to <file>. 49 -p <lang>, --parser=<lang> Select a parser for <lang>. 50 -Wp,<arg>[,<arg>...] Send <args> to the parser. 51 -t [<markup>] 52 --translate[=<markup>] Translate comments to doc-strings, processing it as 53 <markup> (typical values are 'javadoc' or 'rst'). 54 --cfilter=<filter> Specify a comment filter. 55 --cprocessor=<processor> Specify a comment processor. 56 -Wc,<arg>[,<arg>...] Send <args> to the comment translator. 57 -l Run the linker. 58 -Wl,<arg>[,<arg>...] Send <args> to the linker. 59 --linker=<processor> Link, and invoke <processor>. 60 -f <type>, 61 --formatter=<type> Select a formatter for <type>. 62 -Wf,<arg>[,<arg>...] Send <args> to the formatter. 63 -I <path> Add <path> to list of include paths. 64 -D <macro> Add <macro> to list of predefined macros. 65 -s <directory>, 66 --sxr=<directory> Specify sxr directory. If given, process source cross-references. 67 --probe Probe the specified processor. 68""" 69 70def make_processor(argv): 71 """Parse command line options and translate them to 72 processor commands and arguments.""" 73 parser = None 74 parser_opts = {} 75 translator_opts = {} 76 cfilters = {'ss': Comments.SSFilter, 77 'sss': Comments.SSSFilter, 78 'ssd': Comments.SSDFilter, 79 'c': Comments.CFilter, 80 'qt': Comments.QtFilter, 81 'java': Comments.JavaFilter} 82 cprocessors = {'previous': Comments.Previous, 83 'grouper': Comments.Grouper} 84 linker = None 85 linker_opts = {'processors':[]} 86 formatter = None 87 formatter_opts = {} 88 options = {} 89 help = False 90 probe = False 91 92 opts, args = getopt.getopt(argv, 93 'o:p:t:lf:s:I:D:W:jvhVdP', 94 ['output=', 95 'parser=', 'translate=', 'cfilter=', 'cprocessor=', 96 'linker=', 'formatter=', 'sxr=', 97 'version', 'help', 'verbose', 'debug', 'profile', 98 'probe']) 99 100 for o, a in opts: 101 if o in ['-V', '--version']: 102 print 'synopsis version %s (revision %s)'%(config.version, config.revision) 103 sys.exit(0) 104 105 if o in ['-v', '--verbose']: options['verbose'] = True 106 elif o in ['-d', '--debug']: options['debug'] = True 107 elif o in ['-P', '--profile']: options['profile'] = True 108 elif o in ['-o', '--output']: options['output'] = a 109 110 elif o in ['-p', '--parser']: 111 if parser: 112 error('Multiple parsers specified.') 113 parser = __import__('Synopsis.Parsers.%s.Parser'%a, 114 'verbose' in options) 115 116 elif o in ['-t', '--translate']: 117 if 'markup' in translator_opts: 118 error('Multiple translators specified.') 119 translator_opts['markup'] = a or '' 120 121 elif o == '--cfilter': 122 if a not in cfilters: 123 error('%s is not a known comment filter.\n' 124 '\t possible values are : %s' 125 %(a, ', '.join([f for f in cfilters]))) 126 translator_opts['filter'] = cfilters[a]() 127 128 elif o == '--cprocessor': 129 if a not in cprocessors: 130 error('%s is not a known comment processor.\n' 131 '\t possible values are : %s' 132 %(a, ', '.join([p for p in cprocessors]))) 133 if not translator_opts.get('processor'): translator_opts['processor'] = [] 134 translator_opts['processor'].append(cprocessors[a]()) 135 136 elif o == '-l': 137 if not linker: 138 linker = __import__('Synopsis.Processors.Linker', 139 'verbose' in options) 140 141 elif o == '--linker': 142 if not linker: 143 linker = __import__('Synopsis.Processors.Linker', 144 'verbose' in options) 145 linker_opts['processors'].extend([__import__('Synopsis.Processors.%s'%x, 146 'verbose' in options)() 147 for x in a.split(',')]) 148 149 elif o in ['-f', '--formatter']: 150 if formatter: 151 error('Multiple formatters specified.') 152 formatter = __import__('Synopsis.Formatters.%s.Formatter'%a, 153 'verbose' in options) 154 155 elif o == '-I': 156 if not parser_opts.get('cppflags'): parser_opts['cppflags'] = [] 157 parser_opts['cppflags'].append('-I%s'%a) 158 159 elif o == '-D': 160 if not parser_opts.get('cppflags'): parser_opts['cppflags'] = [] 161 parser_opts['cppflags'].append('-D%s'%a) 162 163 elif o == '-W': 164 if a[0] == "p": 165 for o,a in get_options(a[2:].split(','), expect_non_options = False): 166 parser_opts[o.replace('-', '_')] = a 167 elif a[0] == "l": 168 for o,a in get_options(a[2:].split(','), expect_non_options = False): 169 linker_opts[o.replace('-', '_')] = a 170 elif a[0] == "f": 171 for o,a in get_options(a[2:].split(','), expect_non_options = False): 172 formatter_opts[o.replace('-', '_')] = a 173 174 elif o in ['-s', '--sxr']: 175 parser_opts['sxr_prefix'] = a 176 linker_opts['sxr_prefix'] = a 177 formatter_opts['sxr_prefix'] = a 178 179 elif o in ['-h', '--help']: 180 help = True 181 elif o == '--probe': 182 probe = True 183 184 if help: 185 for p in parser, linker, formatter: 186 if not p: continue 187 processor = p() 188 print "Parameters for processor '%s':"%p.__module__ 189 parameters = processor.get_parameters() 190 tab = max(map(lambda x:len(x), parameters.keys())) 191 for p in parameters: 192 print " %-*s %s"%(tab, p, parameters[p].doc) 193 if not (parser or linker or formatter): 194 usage() 195 sys.exit(0) 196 197 # quick hack: if the parser is Cpp, rename the 'cppflags' 198 # options to just 'flags' 199 if parser and parser.__module__ == 'Synopsis.Parsers.Cpp': 200 if parser_opts.has_key('cppflags'): 201 parser_opts['flags'] = parser_opts['cppflags'] 202 del parser_opts['cppflags'] 203 204 if probe: 205 if parser and parser.__module__ == 'Synopsis.Parsers.Cpp': 206 cpp = parser(**parser_opts) 207 info = cpp.probe() 208 if not info: 209 print 'Error: no compiler found' 210 else: 211 print 'Compiler:', info.compiler 212 print 'Flags:', ', '.join(info.flags) 213 print 'Language:', info.language 214 print 'Header search path:\n %s\n'%'\n '.join(info.include_paths) 215 macros = [k + (v and '=%s'%v or '') for (k,v) in info.macros] 216 217 print 'Macro definitions:\n %s\n'%'\n '.join(macros) 218 else: 219 print 'Only the Cpp processor supports probing at this time.' 220 sys.exit(0) 221 222 if not args: 223 usage() 224 sys.exit(0) 225 226 if translator_opts.has_key('processor'): 227 processor = translator_opts['processor'] 228 229 options['input'] = args 230 231 #now instantiate the processor 232 processors = [] 233 if parser: 234 processors.append(parser(**parser_opts)) 235 if translator_opts: 236 processors.append(Comments.Translator(**translator_opts)) 237 if linker: 238 processors.append(linker(**linker_opts)) 239 if formatter: 240 processors.append(formatter(**formatter_opts)) 241 242 return Composite(*processors, **options) 243 244def main(): 245 processor = make_processor(sys.argv[1:]) 246 processor.process(IR.IR()) 247 248if __name__ == '__main__': 249 250 try: 251 main() 252 except getopt.GetoptError, e: 253 error(str(e)) 254 except Error, e: 255 error(str(e)) 256 except KeyboardInterrupt, e: 257 print 'KeyboardInterrupt' 258 except IOError, e: 259 error(str(e))