gobject-introspection r170 - in trunk: . tools



Author: johan
Date: Mon Mar 31 20:38:22 2008
New Revision: 170
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=170&view=rev

Log:
2008-03-31  Johan Dahlin  <johan gnome org>

        * tools/g-ir-scanner:
        Start to build abstract syntax node of scanned sources.
        Add support for cpp options.



Modified:
   trunk/ChangeLog
   trunk/tools/g-ir-scanner

Modified: trunk/tools/g-ir-scanner
==============================================================================
--- trunk/tools/g-ir-scanner	(original)
+++ trunk/tools/g-ir-scanner	Mon Mar 31 20:38:22 2008
@@ -7,51 +7,138 @@
 
 import giscanner
 
+class Symbol(object):
+    def __init__(self, symbol):
+        self.symbol = symbol
+        self.nodes = []
+
+    def __repr__(self):
+        return '%s(%s, %s)>' % (self.__class__.__name__,
+                                self.symbol.ident,
+                                self.nodes)
+
+class Function(Symbol):
+    pass
+
+class Struct(Symbol):
+    pass
+
+class Typedef(Symbol):
+    pass
 
 class Generator(object):
     def __init__(self):
         self._scanner = giscanner.SourceScanner()
+        self._filenames = []
+        self._cpp_options = None
 
-    def add_header(self, filename):
-        filename = os.path.abspath(filename)
+    # Public API
 
-        proc = subprocess.Popen('cpp -U__GNUC__ -I.',
-                                executable='/usr/bin/cpp',
-                                stdin=subprocess.PIPE,
-                                stdout=subprocess.PIPE,
-                                )
-        proc.stdin.write(open(filename).read())
-        proc.stdin.close()
-        retval = proc.wait()
-        if retval != 0:
-            print 'Preprocessing failed'
-            return
+    def set_cpp_options(self, cpp_options):
+        self._cpp_options = cpp_options
 
-        fd = proc.stdout.fileno()
-        self._scanner.parse_file(fd, filename)
+    def parse_file(self, filename):
+        self._parse_one(filename)
+        self._filenames.append(filename)
+
+    def parse_macros(self):
+        self._scanner.set_macro_scan(True)
+        for filename in self._filenames:
+            self._parse_one(filename)
+        self._scanner.set_macro_scan(False)
+
+    def get_symbols(self):
+        for symbol in self._scanner.get_symbols():
+            yield symbol
 
-    add_source = add_header
     def dump(self):
         print '-'*30
         for symbol in self._scanner.get_symbols():
-            print symbol
-            print symbol.ident, symbol.type
-            print symbol.base_type.name
-            print '-'*30
+            print symbol.ident, symbol.base_type.name, symbol.type
+
+    # Private
 
+    def _parse_one(self, filename):
+        if filename.endswith('.c'):
+            # FIXME lex only
+            return
+
+        filename = os.path.abspath(filename)
+        proc = self._preprocess(filename)
+        fd = proc.stdout.fileno()
+        if proc is None:
+            return
+
+        self._scanner.parse_file(fd, filename)
+
+    def _preprocess(self, filename):
+        cpp_args = [
+            'cpp',
+            '-C',
+            '-U__GNUC__',
+            '-I.',
+            ]
+        cpp_args += self._cpp_options
+        proc = subprocess.Popen(
+            cpp_args,
+            bufsize=4096,
+            stdin=subprocess.PIPE,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.STDOUT,
+            )
+        proc.stdin.write('#include <%s>\n' % (filename,))
+        proc.stdin.close()
+        return proc
+
+
+class TreeBuilder(object):
+    def __init__(self, generator):
+        self.generator = generator
+        self.nodes = []
+
+        self._traverse()
+
+    def _traverse(self):
+        for symbol in self.generator.get_symbols():
+            node = self._traverse_one(symbol)
+            if node is not None:
+                self.nodes.append(node)
+
+    def _traverse_one(self, symbol):
+        if symbol.type == giscanner.CSYMBOL_TYPE_FUNCTION:
+            return Function(symbol)
+        elif symbol.type == giscanner.CSYMBOL_TYPE_TYPEDEF:
+            return Typedef(symbol)
+        elif symbol.type == giscanner.CSYMBOL_TYPE_STRUCT:
+            return Struct(symbol)
+        else:
+            print 'unhandled', symbol.type
 
 def main(args):
     if len(args) == 1:
         print 'ERROR: Needs at least one filename.'
         return 0
 
+    filenames = []
+    cpp_options = []
+
     gen = Generator()
     for arg in args[1:]:
-        if arg.endswith('.c'):
-            gen.add_source(arg)
-        elif arg.endswith('.h'):
-            gen.add_header(arg)
+        if (arg.endswith('.c') or
+            arg.endswith('.h')):
+            filenames.append(arg)
+        elif arg.startswith('-') and len(arg) >= 2:
+            if arg[1] in ['I', 'U', 'D']:
+                cpp_options.append(arg)
+        else:
+            print 'Unhandled argument:', arg
+    gen.set_cpp_options(cpp_options)
+
+    for filename in filenames:
+        gen.parse_file(filename)
+    gen.parse_macros()
 
-    gen.dump()
+    builder = TreeBuilder(gen)
+    print builder.nodes
 
 sys.exit(main(sys.argv))



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]