]> Git Repo - qemu.git/blob - scripts/qapi.py
target-ppc: Introduce unrealizefn for PowerPCCPU
[qemu.git] / scripts / qapi.py
1 #
2 # QAPI helper library
3 #
4 # Copyright IBM, Corp. 2011
5 #
6 # Authors:
7 #  Anthony Liguori <[email protected]>
8 #
9 # This work is licensed under the terms of the GNU GPLv2.
10 # See the COPYING.LIB file in the top-level directory.
11
12 from ordereddict import OrderedDict
13
14 builtin_types = [
15     'str', 'int', 'number', 'bool',
16     'int8', 'int16', 'int32', 'int64',
17     'uint8', 'uint16', 'uint32', 'uint64'
18 ]
19
20 def tokenize(data):
21     while len(data):
22         ch = data[0]
23         data = data[1:]
24         if ch in ['{', '}', ':', ',', '[', ']']:
25             yield ch
26         elif ch in ' \n':
27             None
28         elif ch == "'":
29             string = ''
30             esc = False
31             while True:
32                 if (data == ''):
33                     raise Exception("Mismatched quotes")
34                 ch = data[0]
35                 data = data[1:]
36                 if esc:
37                     string += ch
38                     esc = False
39                 elif ch == "\\":
40                     esc = True
41                 elif ch == "'":
42                     break
43                 else:
44                     string += ch
45             yield string
46
47 def parse(tokens):
48     if tokens[0] == '{':
49         ret = OrderedDict()
50         tokens = tokens[1:]
51         while tokens[0] != '}':
52             key = tokens[0]
53             tokens = tokens[1:]
54
55             tokens = tokens[1:] # :
56
57             value, tokens = parse(tokens)
58
59             if tokens[0] == ',':
60                 tokens = tokens[1:]
61
62             ret[key] = value
63         tokens = tokens[1:]
64         return ret, tokens
65     elif tokens[0] == '[':
66         ret = []
67         tokens = tokens[1:]
68         while tokens[0] != ']':
69             value, tokens = parse(tokens)
70             if tokens[0] == ',':
71                 tokens = tokens[1:]
72             ret.append(value)
73         tokens = tokens[1:]
74         return ret, tokens
75     else:
76         return tokens[0], tokens[1:]
77
78 def evaluate(string):
79     return parse(map(lambda x: x, tokenize(string)))[0]
80
81 def parse_schema(fp):
82     exprs = []
83     expr = ''
84     expr_eval = None
85
86     for line in fp:
87         if line.startswith('#') or line == '\n':
88             continue
89
90         if line.startswith(' '):
91             expr += line
92         elif expr:
93             expr_eval = evaluate(expr)
94             if expr_eval.has_key('enum'):
95                 add_enum(expr_eval['enum'])
96             elif expr_eval.has_key('union'):
97                 add_enum('%sKind' % expr_eval['union'])
98             exprs.append(expr_eval)
99             expr = line
100         else:
101             expr += line
102
103     if expr:
104         expr_eval = evaluate(expr)
105         if expr_eval.has_key('enum'):
106             add_enum(expr_eval['enum'])
107         elif expr_eval.has_key('union'):
108             add_enum('%sKind' % expr_eval['union'])
109         exprs.append(expr_eval)
110
111     return exprs
112
113 def parse_args(typeinfo):
114     for member in typeinfo:
115         argname = member
116         argentry = typeinfo[member]
117         optional = False
118         structured = False
119         if member.startswith('*'):
120             argname = member[1:]
121             optional = True
122         if isinstance(argentry, OrderedDict):
123             structured = True
124         yield (argname, argentry, optional, structured)
125
126 def de_camel_case(name):
127     new_name = ''
128     for ch in name:
129         if ch.isupper() and new_name:
130             new_name += '_'
131         if ch == '-':
132             new_name += '_'
133         else:
134             new_name += ch.lower()
135     return new_name
136
137 def camel_case(name):
138     new_name = ''
139     first = True
140     for ch in name:
141         if ch in ['_', '-']:
142             first = True
143         elif first:
144             new_name += ch.upper()
145             first = False
146         else:
147             new_name += ch.lower()
148     return new_name
149
150 def c_var(name, protect=True):
151     # ANSI X3J11/88-090, 3.1.1
152     c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
153                      'default', 'do', 'double', 'else', 'enum', 'extern', 'float',
154                      'for', 'goto', 'if', 'int', 'long', 'register', 'return',
155                      'short', 'signed', 'sizeof', 'static', 'struct', 'switch',
156                      'typedef', 'union', 'unsigned', 'void', 'volatile', 'while'])
157     # ISO/IEC 9899:1999, 6.4.1
158     c99_words = set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
159     # ISO/IEC 9899:2011, 6.4.1
160     c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic', '_Noreturn',
161                      '_Static_assert', '_Thread_local'])
162     # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
163     # excluding _.*
164     gcc_words = set(['asm', 'typeof'])
165     # namespace pollution:
166     polluted_words = set(['unix'])
167     if protect and (name in c89_words | c99_words | c11_words | gcc_words | polluted_words):
168         return "q_" + name
169     return name.replace('-', '_').lstrip("*")
170
171 def c_fun(name, protect=True):
172     return c_var(name, protect).replace('.', '_')
173
174 def c_list_type(name):
175     return '%sList' % name
176
177 def type_name(name):
178     if type(name) == list:
179         return c_list_type(name[0])
180     return name
181
182 enum_types = []
183
184 def add_enum(name):
185     global enum_types
186     enum_types.append(name)
187
188 def is_enum(name):
189     global enum_types
190     return (name in enum_types)
191
192 def c_type(name):
193     if name == 'str':
194         return 'char *'
195     elif name == 'int':
196         return 'int64_t'
197     elif (name == 'int8' or name == 'int16' or name == 'int32' or
198           name == 'int64' or name == 'uint8' or name == 'uint16' or
199           name == 'uint32' or name == 'uint64'):
200         return name + '_t'
201     elif name == 'size':
202         return 'uint64_t'
203     elif name == 'bool':
204         return 'bool'
205     elif name == 'number':
206         return 'double'
207     elif type(name) == list:
208         return '%s *' % c_list_type(name[0])
209     elif is_enum(name):
210         return name
211     elif name == None or len(name) == 0:
212         return 'void'
213     elif name == name.upper():
214         return '%sEvent *' % camel_case(name)
215     else:
216         return '%s *' % name
217
218 def genindent(count):
219     ret = ""
220     for i in range(count):
221         ret += " "
222     return ret
223
224 indent_level = 0
225
226 def push_indent(indent_amount=4):
227     global indent_level
228     indent_level += indent_amount
229
230 def pop_indent(indent_amount=4):
231     global indent_level
232     indent_level -= indent_amount
233
234 def cgen(code, **kwds):
235     indent = genindent(indent_level)
236     lines = code.split('\n')
237     lines = map(lambda x: indent + x, lines)
238     return '\n'.join(lines) % kwds + '\n'
239
240 def mcgen(code, **kwds):
241     return cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
242
243 def basename(filename):
244     return filename.split("/")[-1]
245
246 def guardname(filename):
247     guard = basename(filename).rsplit(".", 1)[0]
248     for substr in [".", " ", "-"]:
249         guard = guard.replace(substr, "_")
250     return guard.upper() + '_H'
251
252 def guardstart(name):
253     return mcgen('''
254
255 #ifndef %(name)s
256 #define %(name)s
257
258 ''',
259                  name=guardname(name))
260
261 def guardend(name):
262     return mcgen('''
263
264 #endif /* %(name)s */
265
266 ''',
267                  name=guardname(name))
This page took 0.036796 seconds and 4 git commands to generate.