Statistics
| Branch: | Revision:

root / scripts / qapi.py @ b9a7b74f

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

255 c0afa9c5 Michael Roth
#ifndef %(name)s
256 c0afa9c5 Michael Roth
#define %(name)s
257 c0afa9c5 Michael Roth

258 c0afa9c5 Michael Roth
''',
259 c0afa9c5 Michael Roth
                 name=guardname(name))
260 c0afa9c5 Michael Roth
261 c0afa9c5 Michael Roth
def guardend(name):
262 c0afa9c5 Michael Roth
    return mcgen('''
263 c0afa9c5 Michael Roth

264 c0afa9c5 Michael Roth
#endif /* %(name)s */
265 c0afa9c5 Michael Roth

266 c0afa9c5 Michael Roth
''',
267 c0afa9c5 Michael Roth
                 name=guardname(name))