qapi: add qapi.py helper libraries
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com> Signed-off-by: Luiz Capitulino <lcapitulino@gmail.com>
This commit is contained in:
parent
e89ac222aa
commit
0f923be253
203
scripts/qapi.py
Normal file
203
scripts/qapi.py
Normal file
@ -0,0 +1,203 @@
|
||||
#
|
||||
# QAPI helper library
|
||||
#
|
||||
# Copyright IBM, Corp. 2011
|
||||
#
|
||||
# Authors:
|
||||
# Anthony Liguori <aliguori@us.ibm.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPLv2.
|
||||
# See the COPYING.LIB file in the top-level directory.
|
||||
|
||||
from ordereddict import OrderedDict
|
||||
|
||||
def tokenize(data):
|
||||
while len(data):
|
||||
if data[0] in ['{', '}', ':', ',', '[', ']']:
|
||||
yield data[0]
|
||||
data = data[1:]
|
||||
elif data[0] in ' \n':
|
||||
data = data[1:]
|
||||
elif data[0] == "'":
|
||||
data = data[1:]
|
||||
string = ''
|
||||
while data[0] != "'":
|
||||
string += data[0]
|
||||
data = data[1:]
|
||||
data = data[1:]
|
||||
yield string
|
||||
|
||||
def parse(tokens):
|
||||
if tokens[0] == '{':
|
||||
ret = OrderedDict()
|
||||
tokens = tokens[1:]
|
||||
while tokens[0] != '}':
|
||||
key = tokens[0]
|
||||
tokens = tokens[1:]
|
||||
|
||||
tokens = tokens[1:] # :
|
||||
|
||||
value, tokens = parse(tokens)
|
||||
|
||||
if tokens[0] == ',':
|
||||
tokens = tokens[1:]
|
||||
|
||||
ret[key] = value
|
||||
tokens = tokens[1:]
|
||||
return ret, tokens
|
||||
elif tokens[0] == '[':
|
||||
ret = []
|
||||
tokens = tokens[1:]
|
||||
while tokens[0] != ']':
|
||||
value, tokens = parse(tokens)
|
||||
if tokens[0] == ',':
|
||||
tokens = tokens[1:]
|
||||
ret.append(value)
|
||||
tokens = tokens[1:]
|
||||
return ret, tokens
|
||||
else:
|
||||
return tokens[0], tokens[1:]
|
||||
|
||||
def evaluate(string):
|
||||
return parse(map(lambda x: x, tokenize(string)))[0]
|
||||
|
||||
def parse_schema(fp):
|
||||
exprs = []
|
||||
expr = ''
|
||||
expr_eval = None
|
||||
|
||||
for line in fp:
|
||||
if line.startswith('#') or line == '\n':
|
||||
continue
|
||||
|
||||
if line.startswith(' '):
|
||||
expr += line
|
||||
elif expr:
|
||||
expr_eval = evaluate(expr)
|
||||
if expr_eval.has_key('enum'):
|
||||
add_enum(expr_eval['enum'])
|
||||
elif expr_eval.has_key('union'):
|
||||
add_enum('%sKind' % expr_eval['union'])
|
||||
exprs.append(expr_eval)
|
||||
expr = line
|
||||
else:
|
||||
expr += line
|
||||
|
||||
if expr:
|
||||
expr_eval = evaluate(expr)
|
||||
if expr_eval.has_key('enum'):
|
||||
add_enum(expr_eval['enum'])
|
||||
elif expr_eval.has_key('union'):
|
||||
add_enum('%sKind' % expr_eval['union'])
|
||||
exprs.append(expr_eval)
|
||||
|
||||
return exprs
|
||||
|
||||
def parse_args(typeinfo):
|
||||
for member in typeinfo:
|
||||
argname = member
|
||||
argentry = typeinfo[member]
|
||||
optional = False
|
||||
structured = False
|
||||
if member.startswith('*'):
|
||||
argname = member[1:]
|
||||
optional = True
|
||||
if isinstance(argentry, OrderedDict):
|
||||
structured = True
|
||||
yield (argname, argentry, optional, structured)
|
||||
|
||||
def de_camel_case(name):
|
||||
new_name = ''
|
||||
for ch in name:
|
||||
if ch.isupper() and new_name:
|
||||
new_name += '_'
|
||||
if ch == '-':
|
||||
new_name += '_'
|
||||
else:
|
||||
new_name += ch.lower()
|
||||
return new_name
|
||||
|
||||
def camel_case(name):
|
||||
new_name = ''
|
||||
first = True
|
||||
for ch in name:
|
||||
if ch in ['_', '-']:
|
||||
first = True
|
||||
elif first:
|
||||
new_name += ch.upper()
|
||||
first = False
|
||||
else:
|
||||
new_name += ch.lower()
|
||||
return new_name
|
||||
|
||||
def c_var(name):
|
||||
return '_'.join(name.split('-')).lstrip("*")
|
||||
|
||||
def c_list_type(name):
|
||||
return '%sList' % name
|
||||
|
||||
def type_name(name):
|
||||
if type(name) == list:
|
||||
return c_list_type(name[0])
|
||||
return name
|
||||
|
||||
enum_types = []
|
||||
|
||||
def add_enum(name):
|
||||
global enum_types
|
||||
enum_types.append(name)
|
||||
|
||||
def is_enum(name):
|
||||
global enum_types
|
||||
return (name in enum_types)
|
||||
|
||||
def c_type(name):
|
||||
if name == 'str':
|
||||
return 'char *'
|
||||
elif name == 'int':
|
||||
return 'int64_t'
|
||||
elif name == 'bool':
|
||||
return 'bool'
|
||||
elif name == 'number':
|
||||
return 'double'
|
||||
elif type(name) == list:
|
||||
return '%s *' % c_list_type(name[0])
|
||||
elif is_enum(name):
|
||||
return name
|
||||
elif name == None or len(name) == 0:
|
||||
return 'void'
|
||||
elif name == name.upper():
|
||||
return '%sEvent *' % camel_case(name)
|
||||
else:
|
||||
return '%s *' % name
|
||||
|
||||
def genindent(count):
|
||||
ret = ""
|
||||
for i in range(count):
|
||||
ret += " "
|
||||
return ret
|
||||
|
||||
indent_level = 0
|
||||
|
||||
def push_indent(indent_amount=4):
|
||||
global indent_level
|
||||
indent_level += indent_amount
|
||||
|
||||
def pop_indent(indent_amount=4):
|
||||
global indent_level
|
||||
indent_level -= indent_amount
|
||||
|
||||
def cgen(code, **kwds):
|
||||
indent = genindent(indent_level)
|
||||
lines = code.split('\n')
|
||||
lines = map(lambda x: indent + x, lines)
|
||||
return '\n'.join(lines) % kwds + '\n'
|
||||
|
||||
def mcgen(code, **kwds):
|
||||
return cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
|
||||
|
||||
def basename(filename):
|
||||
return filename.split("/")[-1]
|
||||
|
||||
def guardname(filename):
|
||||
return filename.replace("/", "_").replace("-", "_").split(".")[0].upper()
|
Loading…
Reference in New Issue
Block a user