qapi.py 5.0 KB

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