1# -*- Mode: Python; py-indent-offset: 4 -*-
2import os, sys
3import scmexpr
4from definitions import BoxedDef, EnumDef, FlagsDef, FunctionDef, \
5     InterfaceDef, MethodDef, ObjectDef, PointerDef, VirtualDef
6
7include_path = ['.']
8
9class IncludeParser(scmexpr.Parser):
10    """A simple parser that follows include statements automatically"""
11    def include(self, input_filename):
12        global include_path
13        if os.path.isabs(input_filename):
14            filename = input_filename
15            # set self.filename to the include name, to handle recursive includes
16            oldfile = self.filename
17            self.filename = filename
18            self.startParsing()
19            self.filename = oldfile
20        else:
21            inc_path = [os.path.dirname(self.filename)] + include_path
22            for filename in [os.path.join(path_entry, input_filename)
23                             for path_entry in inc_path]:
24                if not os.path.exists(filename):
25                    continue
26                # set self.filename to the include name, to handle recursive includes
27                oldfile = self.filename
28                self.filename = filename
29                self.startParsing()
30                self.filename = oldfile
31                break
32            else:
33                raise IOError("%s not found in include path %s" % (input_filename, inc_path))
34
35class DefsParser(IncludeParser):
36    def __init__(self, arg, defines={}):
37        IncludeParser.__init__(self, arg)
38        self.objects = []
39        self.interfaces = []
40        self.enums = []      # enums and flags
41        self.boxes = []      # boxed types
42        self.pointers = []   # pointer types
43        self.functions = []  # functions and methods
44        self.virtuals = []   # virtual methods
45        self.c_name = {}     # hash of c names of functions
46        self.methods = {}    # hash of methods of particular objects
47        self.defines = defines      # -Dfoo=bar options, as dictionary
48
49    def define_object(self, *args):
50        odef = apply(ObjectDef, args)
51        self.objects.append(odef)
52        self.c_name[odef.c_name] = odef
53    def define_interface(self, *args):
54        idef = apply(InterfaceDef, args)
55        self.interfaces.append(idef)
56        self.c_name[idef.c_name] = idef
57    def define_enum(self, *args):
58        edef = apply(EnumDef, args)
59        self.enums.append(edef)
60        self.c_name[edef.c_name] = edef
61    def define_flags(self, *args):
62        fdef = apply(FlagsDef, args)
63        self.enums.append(fdef)
64        self.c_name[fdef.c_name] = fdef
65    def define_boxed(self, *args):
66        bdef = apply(BoxedDef, args)
67        self.boxes.append(bdef)
68        self.c_name[bdef.c_name] = bdef
69    def define_pointer(self, *args):
70        pdef = apply(PointerDef, args)
71        self.pointers.append(pdef)
72        self.c_name[pdef.c_name] = pdef
73    def define_function(self, *args):
74        fdef = apply(FunctionDef, args)
75        self.functions.append(fdef)
76        self.c_name[fdef.c_name] = fdef
77    def define_method(self, *args):
78        mdef = apply(MethodDef, args)
79        self.functions.append(mdef)
80        self.c_name[mdef.c_name] = mdef
81    def define_virtual(self, *args):
82        vdef = apply(VirtualDef, args)
83        self.virtuals.append(vdef)
84    def merge(self, old, parmerge):
85        for obj in self.objects:
86            if old.c_name.has_key(obj.c_name):
87                obj.merge(old.c_name[obj.c_name])
88        for f in self.functions:
89            if old.c_name.has_key(f.c_name):
90                f.merge(old.c_name[f.c_name], parmerge)
91
92    def printMissing(self, old):
93        for obj in self.objects:
94            if not old.c_name.has_key(obj.c_name):
95                obj.write_defs()
96        for f in self.functions:
97            if not old.c_name.has_key(f.c_name):
98                f.write_defs()
99
100    def write_defs(self, fp=sys.stdout):
101        for obj in self.objects:
102            obj.write_defs(fp)
103        for enum in self.enums:
104            enum.write_defs(fp)
105        for boxed in self.boxes:
106            boxed.write_defs(fp)
107        for pointer in self.pointers:
108            pointer.write_defs(fp)
109        for func in self.functions:
110            func.write_defs(fp)
111
112    def find_object(self, c_name):
113        for obj in self.objects:
114            if obj.c_name == c_name:
115                return obj
116        else:
117            raise ValueError('object %r not found' % c_name)
118
119    def find_constructor(self, obj, overrides):
120        for func in self.functions:
121            if isinstance(func, FunctionDef) and \
122               func.is_constructor_of == obj.c_name and \
123               not overrides.is_ignored(func.c_name):
124                return func
125
126    def find_methods(self, obj):
127        objname = obj.c_name
128        return filter(lambda func, on=objname: isinstance(func, MethodDef) and
129                      func.of_object == on, self.functions)
130
131    def find_virtuals(self, obj):
132        objname = obj.c_name
133        retval = filter(lambda func, on=objname: isinstance(func, VirtualDef) and
134                        func.of_object == on, self.virtuals)
135        return retval
136
137    def find_functions(self):
138        return filter(lambda func: isinstance(func, FunctionDef) and
139                      not func.is_constructor_of, self.functions)
140
141    def ifdef(self, *args):
142        if args[0] in self.defines:
143            for arg in args[1:]:
144                #print >> sys.stderr, "-----> Handling conditional definition (%s): %s" % (args[0], arg)
145                self.handle(arg)
146        else:
147            pass
148            #print >> sys.stderr, "-----> Conditional %s is not true" % (args[0],)
149
150    def ifndef(self, *args):
151        if args[0] not in self.defines:
152            for arg in args[1:]:
153                self.handle(arg)
154