Initial release
[adaptation/ap_samsung/gst-plugins-s5pc2xx.git] / common / scangobj-merge.py
1 #!/usr/bin/python
2 # -*- Mode: Python -*-
3 # vi:si:et:sw=4:sts=4:ts=4
4
5 """
6 parse, update and write .signals and .args files
7 """
8
9 from twisted.python import util
10
11 import sys
12 import os
13
14 def debug(*args):
15     pass
16
17 class Object:
18     def __init__(self, name):
19         self._signals = util.OrderedDict()
20         self._args = util.OrderedDict()
21         self.name = name
22
23     def __repr__(self):
24         return "<Object %s>" % self.name
25
26     def add_signal(self, signal, overwrite=True):
27         if not overwrite and self._signals.has_key(signal.name):
28             raise IndexError, "signal %s already in %r" % (signal.name, self)
29         self._signals[signal.name] = signal
30
31     def add_arg(self, arg, overwrite=True):
32         if not overwrite and self._args.has_key(arg.name):
33             raise IndexError, "arg %s already in %r" % (arg.name, self)
34         self._args[arg.name] = arg
35         
36 class Docable:
37     def __init__(self, **kwargs):
38         for key in self.attrs:
39             setattr(self, key, kwargs[key])
40         self.dict = kwargs
41
42     def __repr__(self):
43         return "<%r %s>" % (str(self.__class__), self.name)
44
45 class Signal(Docable):
46     attrs = ['name', 'returns', 'args']
47
48 class Arg(Docable):
49     attrs = ['name', 'type', 'range', 'flags', 'nick', 'blurb', 'default']
50
51 class GDoc:
52     def load_file(self, filename):
53         try:
54             lines = open(filename).readlines()
55             self.load_data("".join(lines))
56         except IOError:
57             print "WARNING - could not read from %s" % filename
58
59     def save_file(self, filename, backup=False):
60         """
61         Save the signals information to the given .signals file if the
62         file content changed.
63         """
64         olddata = None
65         try:
66             lines = open(filename).readlines()
67             olddata = "".join(lines)
68         except IOError:
69             print "WARNING - could not read from %s" % filename
70         newdata = self.get_data()
71         if olddata and olddata == newdata:
72             return
73
74         if olddata:
75             if backup:
76                 os.rename(filename, filename + '.bak')
77
78         handle = open(filename, "w")
79         handle.write(newdata)
80         handle.close()
81
82 class Signals(GDoc):
83     def __init__(self):
84         self._objects = util.OrderedDict()
85
86     def load_data(self, data):
87         """
88         Load the .signals lines, creating our list of objects and signals.
89         """
90         import re
91         smatcher = re.compile(
92             '(?s)'                                      # make . match \n
93             '<SIGNAL>\n(.*?)</SIGNAL>\n'
94             )
95         nmatcher = re.compile(
96             '<NAME>'
97             '(?P<object>\S*)'                           # store object
98             '::'
99             '(?P<signal>\S*)'                           # store signal
100             '</NAME>'
101         )
102         rmatcher = re.compile(
103             '(?s)'                                      # make . match \n
104             '<RETURNS>(?P<returns>\S*)</RETURNS>\n'     # store returns
105             '(?P<args>.*)'                              # store args
106         )
107         for block in smatcher.findall(data):
108             nmatch = nmatcher.search(block)
109             if nmatch:
110                 o = nmatch.group('object')
111                 debug("Found object", o)
112                 debug("Found signal", nmatch.group('signal'))
113                 if not self._objects.has_key(o):
114                     object = Object(o)
115                     self._objects[o] = object
116
117                 rmatch = rmatcher.search(block)
118                 if rmatch:
119                     dict = rmatch.groupdict().copy()
120                     dict['name'] = nmatch.group('signal')
121                     signal = Signal(**dict)
122                     self._objects[o].add_signal(signal)
123
124     def get_data(self):
125         lines = []
126         for o in self._objects.values():
127             for s in o._signals.values():
128                 block = """<SIGNAL>
129 <NAME>%(object)s::%(name)s</NAME>
130 <RETURNS>%(returns)s</RETURNS>
131 %(args)s</SIGNAL>
132 """
133                 d = s.dict.copy()
134                 d['object'] = o.name
135                 lines.append(block % d)
136
137         return "\n".join(lines) + '\n'
138
139 class Args(GDoc):
140     def __init__(self):
141         self._objects = util.OrderedDict()
142
143     def load_data(self, data):
144         """
145         Load the .args lines, creating our list of objects and args.
146         """
147         import re
148         amatcher = re.compile(
149             '(?s)'                                      # make . match \n
150             '<ARG>\n(.*?)</ARG>\n'
151             )
152         nmatcher = re.compile(
153             '<NAME>'
154             '(?P<object>\S*)'                           # store object
155             '::'
156             '(?P<arg>\S*)'                              # store arg
157             '</NAME>'
158         )
159         rmatcher = re.compile(
160             '(?s)'                                      # make . match \n
161             '<TYPE>(?P<type>\S*)</TYPE>\n'              # store type
162             '<RANGE>(?P<range>.*?)</RANGE>\n'           # store range
163             '<FLAGS>(?P<flags>\S*)</FLAGS>\n'           # store flags
164             '<NICK>(?P<nick>.*?)</NICK>\n'              # store nick
165             '<BLURB>(?P<blurb>.*?)</BLURB>\n'           # store blurb
166             '<DEFAULT>(?P<default>.*?)</DEFAULT>\n'     # store default
167         )
168         for block in amatcher.findall(data):
169             nmatch = nmatcher.search(block)
170             if nmatch:
171                 o = nmatch.group('object')
172                 debug("Found object", o)
173                 debug("Found arg", nmatch.group('arg'))
174                 if not self._objects.has_key(o):
175                     object = Object(o)
176                     self._objects[o] = object
177
178                 rmatch = rmatcher.search(block)
179                 if rmatch:
180                     dict = rmatch.groupdict().copy()
181                     dict['name'] = nmatch.group('arg')
182                     arg = Arg(**dict)
183                     self._objects[o].add_arg(arg)
184                 else:
185                     print "ERROR: could not match arg from block %s" % block
186
187     def get_data(self):
188         lines = []
189         for o in self._objects.values():
190             for a in o._args.values():
191                 block = """<ARG>
192 <NAME>%(object)s::%(name)s</NAME>
193 <TYPE>%(type)s</TYPE>
194 <RANGE>%(range)s</RANGE>
195 <FLAGS>%(flags)s</FLAGS>
196 <NICK>%(nick)s</NICK>
197 <BLURB>%(blurb)s</BLURB>
198 <DEFAULT>%(default)s</DEFAULT>
199 </ARG>
200 """
201                 d = a.dict.copy()
202                 d['object'] = o.name
203                 lines.append(block % d)
204
205         return "\n".join(lines) + '\n'
206
207 def main(argv):
208     modulename = None
209     try:
210         modulename = argv[1]
211     except IndexError:
212         sys.stderr.write('Pleae provide a documentation module name\n')
213         sys.exit(1)
214
215     print "Merging scangobj output for %s" % modulename
216     signals = Signals()
217     signals.load_file(modulename + '.signals')
218     signals.load_file(modulename + '.signals.new')
219     signals.save_file(modulename + '.signals', backup=True)
220
221     args = Args()
222     args.load_file(modulename + '.args')
223     args.load_file(modulename + '.args.new')
224     args.save_file(modulename + '.args', backup=True)
225
226 main(sys.argv)