diff options
Diffstat (limited to 'giscanner/scannermain.py')
-rwxr-xr-x | giscanner/scannermain.py | 132 |
1 files changed, 100 insertions, 32 deletions
diff --git a/giscanner/scannermain.py b/giscanner/scannermain.py index 794cede3..98d56878 100755 --- a/giscanner/scannermain.py +++ b/giscanner/scannermain.py @@ -27,9 +27,10 @@ import shutil import subprocess import sys import tempfile +import platform from giscanner import message -from giscanner.annotationparser import AnnotationParser +from giscanner.annotationparser import GtkDocCommentBlockParser from giscanner.ast import Include, Namespace from giscanner.dumper import compile_introspection_binary from giscanner.gdumpparser import GDumpParser, IntrospectionBinary @@ -38,15 +39,42 @@ from giscanner.girparser import GIRParser from giscanner.girwriter import GIRWriter from giscanner.maintransformer import MainTransformer from giscanner.shlibs import resolve_shlibs -from giscanner.sourcescanner import SourceScanner +from giscanner.sourcescanner import SourceScanner, ALL_EXTS from giscanner.transformer import Transformer from . import utils + +def process_cflags_begin(option, opt, value, parser): + cflags = getattr(parser.values, option.dest) + while len(parser.rargs) > 0 and parser.rargs[0] != '--cflags-end': + arg = parser.rargs.pop(0) + if arg == "-I" and parser.rargs and parser.rargs[0] != '--cflags-end': + # This is a special case where there's a space between -I and the path. + arg += parser.rargs.pop(0) + cflags.append(utils.cflag_real_include_path(arg)) + + +def process_cflags_end(option, opt, value, parser): + pass + + +def process_cpp_includes(option, opt, value, parser): + cpp_includes = getattr(parser.values, option.dest) + cpp_includes.append(os.path.realpath(value)) + + def get_preprocessor_option_group(parser): group = optparse.OptionGroup(parser, "Preprocessor options") + group.add_option("", "--cflags-begin", + help="Start preprocessor/compiler flags", + dest="cflags", default=[], + action="callback", callback=process_cflags_begin) + group.add_option("", "--cflags-end", + help="End preprocessor/compiler flags", + action="callback", callback=process_cflags_end) group.add_option("-I", help="Pre-processor include file", - action="append", dest="cpp_includes", - default=[]) + dest="cpp_includes", default=[], type="string", + action="callback", callback=process_cpp_includes) group.add_option("-D", help="Pre-processor define", action="append", dest="cpp_defines", default=[]) @@ -56,6 +84,7 @@ def get_preprocessor_option_group(parser): group.add_option("-p", dest="", help="Ignored") return group + def get_windows_option_group(parser): group = optparse.OptionGroup(parser, "Machine Dependent Options") group.add_option("-m", help="some machine dependent option", @@ -64,13 +93,13 @@ def get_windows_option_group(parser): return group + def _get_option_parser(): parser = optparse.OptionParser('%prog [options] sources') parser.add_option('', "--quiet", action="store_true", dest="quiet", default=False, - help="If passed, do not print details of normal" \ - + " operation") + help="If passed, do not print details of normal operation") parser.add_option("", "--format", action="store", dest="format", default="gir", @@ -158,6 +187,9 @@ match the namespace prefix.""") parser.add_option("", "--c-include", action="append", dest="c_includes", default=[], help="headers which should be included in C programs") + parser.add_option("", "--filelist", + action="store", dest="filelist", default=[], + help="file containing headers and sources to be scanned") group = get_preprocessor_option_group(parser) parser.add_option_group(group) @@ -186,17 +218,15 @@ match the namespace prefix.""") def _error(msg): raise SystemExit('ERROR: %s' % (msg, )) + def passthrough_gir(path, f): parser = GIRParser() parser.parse(path) - writer = GIRWriter(parser.get_namespace(), - parser.get_shared_libraries(), - parser.get_includes(), - parser.get_pkgconfig_packages(), - parser.get_c_includes()) + writer = GIRWriter(parser.get_namespace()) f.write(writer.get_xml()) + def test_codegen(optstring): (namespace, out_h_filename, out_c_filename) = optstring.split(',') if namespace == 'Everything': @@ -207,6 +237,7 @@ def test_codegen(optstring): _error("Invaild namespace %r" % (namespace, )) return 0 + def process_options(output, allowed_flags): for option in output.split(): for flag in allowed_flags: @@ -215,6 +246,7 @@ def process_options(output, allowed_flags): yield option break + def process_packages(options, packages): args = ['pkg-config', '--cflags'] args.extend(packages) @@ -230,26 +262,47 @@ def process_packages(options, packages): filtered_output = list(process_options(output, options_whitelist)) parser = _get_option_parser() pkg_options, unused = parser.parse_args(filtered_output) - options.cpp_includes.extend(pkg_options.cpp_includes) + options.cpp_includes.extend([os.path.realpath(f) for f in pkg_options.cpp_includes]) options.cpp_defines.extend(pkg_options.cpp_defines) options.cpp_undefines.extend(pkg_options.cpp_undefines) + def extract_filenames(args): filenames = [] for arg in args: # We don't support real C++ parsing yet, but we should be able # to understand C API implemented in C++ files. - if (arg.endswith('.c') or arg.endswith('.cpp') or - arg.endswith('.cc') or arg.endswith('.cxx') or - arg.endswith('.h') or arg.endswith('.hpp') or - arg.endswith('.hxx')): + if os.path.splitext(arg)[1] in ALL_EXTS: if not os.path.exists(arg): _error('%s: no such a file or directory' % (arg, )) # Make absolute, because we do comparisons inside scannerparser.c # against the absolute path that cpp will give us - filenames.append(os.path.abspath(arg)) + filenames.append(arg) return filenames + +def extract_filelist(options): + filenames = [] + if not os.path.exists(options.filelist): + _error('%s: no such filelist file' % (options.filelist, )) + filelist_file = open(options.filelist, "r") + lines = filelist_file.readlines() + for line in lines: + # We don't support real C++ parsing yet, but we should be able + # to understand C API implemented in C++ files. + filename = line.strip() + if (filename.endswith('.c') or filename.endswith('.cpp') + or filename.endswith('.cc') or filename.endswith('.cxx') + or filename.endswith('.h') or filename.endswith('.hpp') + or filename.endswith('.hxx')): + if not os.path.exists(filename): + _error('%s: Invalid filelist entry-no such file or directory' % (line, )) + # Make absolute, because we do comparisons inside scannerparser.c + # against the absolute path that cpp will give us + filenames.append(filename) + return filenames + + def create_namespace(options): if options.strip_prefix: print """g-ir-scanner: warning: Option --strip-prefix has been deprecated; @@ -278,6 +331,7 @@ see --identifier-prefix and --symbol-prefix.""" identifier_prefixes=identifier_prefixes, symbol_prefixes=symbol_prefixes) + def create_transformer(namespace, options): transformer = Transformer(namespace, accept_unprefixed=options.accept_unprefixed) @@ -286,7 +340,6 @@ def create_transformer(namespace, options): transformer.disable_cache() transformer.set_passthrough_mode() - shown_include_warning = False for include in options.includes: if os.sep in include: _error("Invalid include path %r" % (include, )) @@ -300,6 +353,7 @@ def create_transformer(namespace, options): return transformer + def create_binary(transformer, options, args): # Transform the C AST nodes into higher level # GLib/GObject nodes @@ -310,7 +364,7 @@ def create_binary(transformer, options, args): gdump_parser.init_parse() if options.program: - args=[options.program] + args = [options.program] args.extend(options.program_args) binary = IntrospectionBinary(args) else: @@ -323,19 +377,28 @@ def create_binary(transformer, options, args): gdump_parser.parse() return shlibs + def create_source_scanner(options, args): - filenames = extract_filenames(args) + if hasattr(options, 'filelist') and options.filelist: + filenames = extract_filelist(options) + else: + filenames = extract_filenames(args) + + if platform.system() == 'Darwin': + options.cpp_undefines.append('__BLOCKS__') # Run the preprocessor, tokenize and construct simple # objects representing the raw C symbols ss = SourceScanner() ss.set_cpp_options(options.cpp_includes, options.cpp_defines, - options.cpp_undefines) + options.cpp_undefines, + cflags=options.cflags) ss.parse_files(filenames) ss.parse_macros(filenames) return ss + def write_output(data, options): if options.output == "-": output = sys.stdout @@ -355,7 +418,7 @@ def write_output(data, options): os.unlink(temp_f_name) try: shutil.move(main_f_name, options.output) - except OSError, e: + except OSError as e: if e.errno == errno.EPERM: os.unlink(main_f_name) return 0 @@ -364,14 +427,15 @@ def write_output(data, options): else: try: output = open(options.output, "w") - except IOError, e: + except IOError as e: _error("opening output for writing: %s" % (e.strerror, )) try: output.write(data) - except IOError, e: + except IOError as e: _error("while writing output: %s" % (e.strerror, )) + def scanner_main(args): parser = _get_option_parser() (options, args) = parser.parse_args(args) @@ -381,8 +445,9 @@ def scanner_main(args): if options.test_codegen: return test_codegen(options.test_codegen) - if len(args) <= 1: - _error('Need at least one filename') + if hasattr(options, 'filelist') and not options.filelist: + if len(args) <= 1: + _error('Need at least one filename') if not options.namespace_name: _error('Namespace name missing') @@ -400,7 +465,8 @@ def scanner_main(args): namespace = create_namespace(options) logger = message.MessageLogger.get(namespace=namespace) if options.warn_all: - logger.enable_warnings(True) + logger.enable_warnings((message.WARNING, message.ERROR, message.FATAL)) + transformer = create_transformer(namespace, options) packages = set(options.packages) @@ -412,11 +478,10 @@ def scanner_main(args): ss = create_source_scanner(options, args) - ap = AnnotationParser() - blocks = ap.parse(ss.get_comments()) + cbp = GtkDocCommentBlockParser() + blocks = cbp.parse_comment_blocks(ss.get_comments()) # Transform the C symbols into AST nodes - transformer.set_annotations(blocks) transformer.parse(ss.get_symbols()) if not options.header_only: @@ -424,6 +489,8 @@ def scanner_main(args): else: shlibs = [] + transformer.namespace.shared_libraries = shlibs + main = MainTransformer(transformer, blocks) main.transform() @@ -446,8 +513,9 @@ def scanner_main(args): else: exported_packages = options.packages - writer = Writer(transformer.namespace, shlibs, transformer.get_includes(), - exported_packages, options.c_includes) + transformer.namespace.c_includes = options.c_includes + transformer.namespace.exported_packages = exported_packages + writer = Writer(transformer.namespace) data = writer.get_xml() write_output(data, options) |