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