root / scripts / qapi.py @ 0f923be2
History | View | Annotate | Download (4.8 kB)
1 | 0f923be2 | Michael Roth | #
|
---|---|---|---|
2 | 0f923be2 | Michael Roth | # QAPI helper library
|
3 | 0f923be2 | Michael Roth | #
|
4 | 0f923be2 | Michael Roth | # Copyright IBM, Corp. 2011
|
5 | 0f923be2 | Michael Roth | #
|
6 | 0f923be2 | Michael Roth | # Authors:
|
7 | 0f923be2 | Michael Roth | # Anthony Liguori <aliguori@us.ibm.com>
|
8 | 0f923be2 | Michael Roth | #
|
9 | 0f923be2 | Michael Roth | # This work is licensed under the terms of the GNU GPLv2.
|
10 | 0f923be2 | Michael Roth | # See the COPYING.LIB file in the top-level directory.
|
11 | 0f923be2 | Michael Roth | |
12 | 0f923be2 | Michael Roth | from ordereddict import OrderedDict |
13 | 0f923be2 | Michael Roth | |
14 | 0f923be2 | Michael Roth | def tokenize(data): |
15 | 0f923be2 | Michael Roth | while len(data): |
16 | 0f923be2 | Michael Roth | if data[0] in ['{', '}', ':', ',', '[', ']']: |
17 | 0f923be2 | Michael Roth | yield data[0] |
18 | 0f923be2 | Michael Roth | data = data[1:]
|
19 | 0f923be2 | Michael Roth | elif data[0] in ' \n': |
20 | 0f923be2 | Michael Roth | data = data[1:]
|
21 | 0f923be2 | Michael Roth | elif data[0] == "'": |
22 | 0f923be2 | Michael Roth | data = data[1:]
|
23 | 0f923be2 | Michael Roth | string = ''
|
24 | 0f923be2 | Michael Roth | while data[0] != "'": |
25 | 0f923be2 | Michael Roth | string += data[0]
|
26 | 0f923be2 | Michael Roth | data = data[1:]
|
27 | 0f923be2 | Michael Roth | data = data[1:]
|
28 | 0f923be2 | Michael Roth | yield string
|
29 | 0f923be2 | Michael Roth | |
30 | 0f923be2 | Michael Roth | def parse(tokens): |
31 | 0f923be2 | Michael Roth | if tokens[0] == '{': |
32 | 0f923be2 | Michael Roth | ret = OrderedDict() |
33 | 0f923be2 | Michael Roth | tokens = tokens[1:]
|
34 | 0f923be2 | Michael Roth | while tokens[0] != '}': |
35 | 0f923be2 | Michael Roth | key = tokens[0]
|
36 | 0f923be2 | Michael Roth | tokens = tokens[1:]
|
37 | 0f923be2 | Michael Roth | |
38 | 0f923be2 | Michael Roth | tokens = tokens[1:] # : |
39 | 0f923be2 | Michael Roth | |
40 | 0f923be2 | Michael Roth | value, tokens = parse(tokens) |
41 | 0f923be2 | Michael Roth | |
42 | 0f923be2 | Michael Roth | if tokens[0] == ',': |
43 | 0f923be2 | Michael Roth | tokens = tokens[1:]
|
44 | 0f923be2 | Michael Roth | |
45 | 0f923be2 | Michael Roth | ret[key] = value |
46 | 0f923be2 | Michael Roth | tokens = tokens[1:]
|
47 | 0f923be2 | Michael Roth | return ret, tokens
|
48 | 0f923be2 | Michael Roth | elif tokens[0] == '[': |
49 | 0f923be2 | Michael Roth | ret = [] |
50 | 0f923be2 | Michael Roth | tokens = tokens[1:]
|
51 | 0f923be2 | Michael Roth | while tokens[0] != ']': |
52 | 0f923be2 | Michael Roth | value, tokens = parse(tokens) |
53 | 0f923be2 | Michael Roth | if tokens[0] == ',': |
54 | 0f923be2 | Michael Roth | tokens = tokens[1:]
|
55 | 0f923be2 | Michael Roth | ret.append(value) |
56 | 0f923be2 | Michael Roth | tokens = tokens[1:]
|
57 | 0f923be2 | Michael Roth | return ret, tokens
|
58 | 0f923be2 | Michael Roth | else:
|
59 | 0f923be2 | Michael Roth | return tokens[0], tokens[1:] |
60 | 0f923be2 | Michael Roth | |
61 | 0f923be2 | Michael Roth | def evaluate(string): |
62 | 0f923be2 | Michael Roth | return parse(map(lambda x: x, tokenize(string)))[0] |
63 | 0f923be2 | Michael Roth | |
64 | 0f923be2 | Michael Roth | def parse_schema(fp): |
65 | 0f923be2 | Michael Roth | exprs = [] |
66 | 0f923be2 | Michael Roth | expr = ''
|
67 | 0f923be2 | Michael Roth | expr_eval = None
|
68 | 0f923be2 | Michael Roth | |
69 | 0f923be2 | Michael Roth | for line in fp: |
70 | 0f923be2 | Michael Roth | if line.startswith('#') or line == '\n': |
71 | 0f923be2 | Michael Roth | continue
|
72 | 0f923be2 | Michael Roth | |
73 | 0f923be2 | Michael Roth | if line.startswith(' '): |
74 | 0f923be2 | Michael Roth | expr += line |
75 | 0f923be2 | Michael Roth | elif expr:
|
76 | 0f923be2 | Michael Roth | expr_eval = evaluate(expr) |
77 | 0f923be2 | Michael Roth | if expr_eval.has_key('enum'): |
78 | 0f923be2 | Michael Roth | add_enum(expr_eval['enum'])
|
79 | 0f923be2 | Michael Roth | elif expr_eval.has_key('union'): |
80 | 0f923be2 | Michael Roth | add_enum('%sKind' % expr_eval['union']) |
81 | 0f923be2 | Michael Roth | exprs.append(expr_eval) |
82 | 0f923be2 | Michael Roth | expr = line |
83 | 0f923be2 | Michael Roth | else:
|
84 | 0f923be2 | Michael Roth | expr += line |
85 | 0f923be2 | Michael Roth | |
86 | 0f923be2 | Michael Roth | if expr:
|
87 | 0f923be2 | Michael Roth | expr_eval = evaluate(expr) |
88 | 0f923be2 | Michael Roth | if expr_eval.has_key('enum'): |
89 | 0f923be2 | Michael Roth | add_enum(expr_eval['enum'])
|
90 | 0f923be2 | Michael Roth | elif expr_eval.has_key('union'): |
91 | 0f923be2 | Michael Roth | add_enum('%sKind' % expr_eval['union']) |
92 | 0f923be2 | Michael Roth | exprs.append(expr_eval) |
93 | 0f923be2 | Michael Roth | |
94 | 0f923be2 | Michael Roth | return exprs
|
95 | 0f923be2 | Michael Roth | |
96 | 0f923be2 | Michael Roth | def parse_args(typeinfo): |
97 | 0f923be2 | Michael Roth | for member in typeinfo: |
98 | 0f923be2 | Michael Roth | argname = member |
99 | 0f923be2 | Michael Roth | argentry = typeinfo[member] |
100 | 0f923be2 | Michael Roth | optional = False
|
101 | 0f923be2 | Michael Roth | structured = False
|
102 | 0f923be2 | Michael Roth | if member.startswith('*'): |
103 | 0f923be2 | Michael Roth | argname = member[1:]
|
104 | 0f923be2 | Michael Roth | optional = True
|
105 | 0f923be2 | Michael Roth | if isinstance(argentry, OrderedDict): |
106 | 0f923be2 | Michael Roth | structured = True
|
107 | 0f923be2 | Michael Roth | yield (argname, argentry, optional, structured)
|
108 | 0f923be2 | Michael Roth | |
109 | 0f923be2 | Michael Roth | def de_camel_case(name): |
110 | 0f923be2 | Michael Roth | new_name = ''
|
111 | 0f923be2 | Michael Roth | for ch in name: |
112 | 0f923be2 | Michael Roth | if ch.isupper() and new_name: |
113 | 0f923be2 | Michael Roth | new_name += '_'
|
114 | 0f923be2 | Michael Roth | if ch == '-': |
115 | 0f923be2 | Michael Roth | new_name += '_'
|
116 | 0f923be2 | Michael Roth | else:
|
117 | 0f923be2 | Michael Roth | new_name += ch.lower() |
118 | 0f923be2 | Michael Roth | return new_name
|
119 | 0f923be2 | Michael Roth | |
120 | 0f923be2 | Michael Roth | def camel_case(name): |
121 | 0f923be2 | Michael Roth | new_name = ''
|
122 | 0f923be2 | Michael Roth | first = True
|
123 | 0f923be2 | Michael Roth | for ch in name: |
124 | 0f923be2 | Michael Roth | if ch in ['_', '-']: |
125 | 0f923be2 | Michael Roth | first = True
|
126 | 0f923be2 | Michael Roth | elif first:
|
127 | 0f923be2 | Michael Roth | new_name += ch.upper() |
128 | 0f923be2 | Michael Roth | first = False
|
129 | 0f923be2 | Michael Roth | else:
|
130 | 0f923be2 | Michael Roth | new_name += ch.lower() |
131 | 0f923be2 | Michael Roth | return new_name
|
132 | 0f923be2 | Michael Roth | |
133 | 0f923be2 | Michael Roth | def c_var(name): |
134 | 0f923be2 | Michael Roth | return '_'.join(name.split('-')).lstrip("*") |
135 | 0f923be2 | Michael Roth | |
136 | 0f923be2 | Michael Roth | def c_list_type(name): |
137 | 0f923be2 | Michael Roth | return '%sList' % name |
138 | 0f923be2 | Michael Roth | |
139 | 0f923be2 | Michael Roth | def type_name(name): |
140 | 0f923be2 | Michael Roth | if type(name) == list: |
141 | 0f923be2 | Michael Roth | return c_list_type(name[0]) |
142 | 0f923be2 | Michael Roth | return name
|
143 | 0f923be2 | Michael Roth | |
144 | 0f923be2 | Michael Roth | enum_types = [] |
145 | 0f923be2 | Michael Roth | |
146 | 0f923be2 | Michael Roth | def add_enum(name): |
147 | 0f923be2 | Michael Roth | global enum_types
|
148 | 0f923be2 | Michael Roth | enum_types.append(name) |
149 | 0f923be2 | Michael Roth | |
150 | 0f923be2 | Michael Roth | def is_enum(name): |
151 | 0f923be2 | Michael Roth | global enum_types
|
152 | 0f923be2 | Michael Roth | return (name in enum_types) |
153 | 0f923be2 | Michael Roth | |
154 | 0f923be2 | Michael Roth | def c_type(name): |
155 | 0f923be2 | Michael Roth | if name == 'str': |
156 | 0f923be2 | Michael Roth | return 'char *' |
157 | 0f923be2 | Michael Roth | elif name == 'int': |
158 | 0f923be2 | Michael Roth | return 'int64_t' |
159 | 0f923be2 | Michael Roth | elif name == 'bool': |
160 | 0f923be2 | Michael Roth | return 'bool' |
161 | 0f923be2 | Michael Roth | elif name == 'number': |
162 | 0f923be2 | Michael Roth | return 'double' |
163 | 0f923be2 | Michael Roth | elif type(name) == list: |
164 | 0f923be2 | Michael Roth | return '%s *' % c_list_type(name[0]) |
165 | 0f923be2 | Michael Roth | elif is_enum(name):
|
166 | 0f923be2 | Michael Roth | return name
|
167 | 0f923be2 | Michael Roth | elif name == None or len(name) == 0: |
168 | 0f923be2 | Michael Roth | return 'void' |
169 | 0f923be2 | Michael Roth | elif name == name.upper():
|
170 | 0f923be2 | Michael Roth | return '%sEvent *' % camel_case(name) |
171 | 0f923be2 | Michael Roth | else:
|
172 | 0f923be2 | Michael Roth | return '%s *' % name |
173 | 0f923be2 | Michael Roth | |
174 | 0f923be2 | Michael Roth | def genindent(count): |
175 | 0f923be2 | Michael Roth | ret = ""
|
176 | 0f923be2 | Michael Roth | for i in range(count): |
177 | 0f923be2 | Michael Roth | ret += " "
|
178 | 0f923be2 | Michael Roth | return ret
|
179 | 0f923be2 | Michael Roth | |
180 | 0f923be2 | Michael Roth | indent_level = 0
|
181 | 0f923be2 | Michael Roth | |
182 | 0f923be2 | Michael Roth | def push_indent(indent_amount=4): |
183 | 0f923be2 | Michael Roth | global indent_level
|
184 | 0f923be2 | Michael Roth | indent_level += indent_amount |
185 | 0f923be2 | Michael Roth | |
186 | 0f923be2 | Michael Roth | def pop_indent(indent_amount=4): |
187 | 0f923be2 | Michael Roth | global indent_level
|
188 | 0f923be2 | Michael Roth | indent_level -= indent_amount |
189 | 0f923be2 | Michael Roth | |
190 | 0f923be2 | Michael Roth | def cgen(code, **kwds): |
191 | 0f923be2 | Michael Roth | indent = genindent(indent_level) |
192 | 0f923be2 | Michael Roth | lines = code.split('\n')
|
193 | 0f923be2 | Michael Roth | lines = map(lambda x: indent + x, lines) |
194 | 0f923be2 | Michael Roth | return '\n'.join(lines) % kwds + '\n' |
195 | 0f923be2 | Michael Roth | |
196 | 0f923be2 | Michael Roth | def mcgen(code, **kwds): |
197 | 0f923be2 | Michael Roth | return cgen('\n'.join(code.split('\n')[1:-1]), **kwds) |
198 | 0f923be2 | Michael Roth | |
199 | 0f923be2 | Michael Roth | def basename(filename): |
200 | 0f923be2 | Michael Roth | return filename.split("/")[-1] |
201 | 0f923be2 | Michael Roth | |
202 | 0f923be2 | Michael Roth | def guardname(filename): |
203 | 0f923be2 | Michael Roth | return filename.replace("/", "_").replace("-", "_").split(".")[0].upper() |