]> Git Repo - qemu.git/blame - scripts/qapi/common.py
qapi/schema: Clean up around QAPISchemaEntity.connect_doc()
[qemu.git] / scripts / qapi / common.py
CommitLineData
0f923be2
MR
1#
2# QAPI helper library
3#
4# Copyright IBM, Corp. 2011
47a6ea9a 5# Copyright (c) 2013-2018 Red Hat Inc.
0f923be2
MR
6#
7# Authors:
8# Anthony Liguori <[email protected]>
c7a3f252 9# Markus Armbruster <[email protected]>
0f923be2 10#
678e48a2
MA
11# This work is licensed under the terms of the GNU GPL, version 2.
12# See the COPYING file in the top-level directory.
0f923be2 13
c2613949 14import re
0f923be2 15
437db254 16
849bc538
MA
17# ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
18# ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
19# ENUM24_Name -> ENUM24_NAME
20def camel_to_upper(value):
21 c_fun_str = c_name(value, False)
22 if value.isupper():
23 return c_fun_str
24
25 new_name = ''
b736e25a
MA
26 length = len(c_fun_str)
27 for i in range(length):
849bc538 28 c = c_fun_str[i]
ef801a9b
MA
29 # When c is upper and no '_' appears before, do more checks
30 if c.isupper() and (i > 0) and c_fun_str[i - 1] != '_':
b736e25a 31 if i < length - 1 and c_fun_str[i + 1].islower():
437db254
EB
32 new_name += '_'
33 elif c_fun_str[i - 1].isdigit():
849bc538
MA
34 new_name += '_'
35 new_name += c
36 return new_name.lstrip('_').upper()
37
437db254 38
351d36e4
DB
39def c_enum_const(type_name, const_name, prefix=None):
40 if prefix is not None:
41 type_name = prefix
d20a580b 42 return camel_to_upper(type_name) + '_' + c_name(const_name, False).upper()
849bc538 43
b736e25a 44
ed39c03e 45c_name_trans = str.maketrans('.-', '__')
47299262 46
437db254 47
c6405b54
EB
48# Map @name to a valid C identifier.
49# If @protect, avoid returning certain ticklish identifiers (like
ef801a9b 50# C keywords) by prepending 'q_'.
c6405b54
EB
51#
52# Used for converting 'name' from a 'name':'type' qapi definition
53# into a generated struct member, as well as converting type names
54# into substrings of a generated C function name.
55# '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
56# protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
18df515e 57def c_name(name, protect=True):
427a1a2c
BS
58 # ANSI X3J11/88-090, 3.1.1
59 c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
437db254
EB
60 'default', 'do', 'double', 'else', 'enum', 'extern',
61 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
62 'return', 'short', 'signed', 'sizeof', 'static',
63 'struct', 'switch', 'typedef', 'union', 'unsigned',
64 'void', 'volatile', 'while'])
427a1a2c
BS
65 # ISO/IEC 9899:1999, 6.4.1
66 c99_words = set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
67 # ISO/IEC 9899:2011, 6.4.1
437db254
EB
68 c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
69 '_Noreturn', '_Static_assert', '_Thread_local'])
427a1a2c
BS
70 # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
71 # excluding _.*
72 gcc_words = set(['asm', 'typeof'])
6f88009e
TS
73 # C++ ISO/IEC 14882:2003 2.11
74 cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete',
75 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
76 'namespace', 'new', 'operator', 'private', 'protected',
77 'public', 'reinterpret_cast', 'static_cast', 'template',
78 'this', 'throw', 'true', 'try', 'typeid', 'typename',
79 'using', 'virtual', 'wchar_t',
80 # alternative representations
81 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
82 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
1057725f 83 # namespace pollution:
9a801c7d 84 polluted_words = set(['unix', 'errno', 'mips', 'sparc', 'i386'])
c43567c1 85 name = name.translate(c_name_trans)
437db254
EB
86 if protect and (name in c89_words | c99_words | c11_words | gcc_words
87 | cpp_words | polluted_words):
ef801a9b 88 return 'q_' + name
c43567c1 89 return name
0f923be2 90
b736e25a 91
05dfb26c 92eatspace = '\033EATSPACE.'
d5573446 93pointer_suffix = ' *' + eatspace
05dfb26c 94
437db254 95
0f923be2 96def genindent(count):
ef801a9b 97 ret = ''
437db254 98 for _ in range(count):
ef801a9b 99 ret += ' '
0f923be2
MR
100 return ret
101
b736e25a 102
0f923be2
MR
103indent_level = 0
104
437db254 105
0f923be2
MR
106def push_indent(indent_amount=4):
107 global indent_level
108 indent_level += indent_amount
109
437db254 110
0f923be2
MR
111def pop_indent(indent_amount=4):
112 global indent_level
113 indent_level -= indent_amount
114
437db254 115
77e703b8
MA
116# Generate @code with @kwds interpolated.
117# Obey indent_level, and strip eatspace.
0f923be2 118def cgen(code, **kwds):
77e703b8
MA
119 raw = code % kwds
120 if indent_level:
121 indent = genindent(indent_level)
2752e5be 122 # re.subn() lacks flags support before Python 2.7, use re.compile()
485d948c
MAL
123 raw = re.subn(re.compile(r'^(?!(#|$))', re.MULTILINE),
124 indent, raw)
77e703b8 125 raw = raw[0]
0fe675af 126 return re.sub(re.escape(eatspace) + r' *', '', raw)
0f923be2 127
437db254 128
0f923be2 129def mcgen(code, **kwds):
77e703b8
MA
130 if code[0] == '\n':
131 code = code[1:]
132 return cgen(code, **kwds)
0f923be2 133
0f923be2 134
709395f8
MA
135def c_fname(filename):
136 return re.sub(r'[^A-Za-z0-9_]', '_', filename)
c0afa9c5 137
437db254 138
c0afa9c5
MR
139def guardstart(name):
140 return mcgen('''
c0afa9c5
MR
141#ifndef %(name)s
142#define %(name)s
143
144''',
709395f8 145 name=c_fname(name).upper())
c0afa9c5 146
437db254 147
c0afa9c5
MR
148def guardend(name):
149 return mcgen('''
150
151#endif /* %(name)s */
c0afa9c5 152''',
709395f8 153 name=c_fname(name).upper())
2114f5a9 154
437db254 155
ded9fc28
MAL
156def gen_if(ifcond):
157 ret = ''
158 for ifc in ifcond:
159 ret += mcgen('''
160#if %(cond)s
161''', cond=ifc)
162 return ret
163
164
165def gen_endif(ifcond):
166 ret = ''
167 for ifc in reversed(ifcond):
168 ret += mcgen('''
169#endif /* %(cond)s */
170''', cond=ifc)
171 return ret
172
173
bdd2d42b 174def build_params(arg_type, boxed, extra=None):
03b4367a
MA
175 ret = ''
176 sep = ''
48825ca4 177 if boxed:
bdd2d42b 178 assert arg_type
c818408e
EB
179 ret += '%s arg' % arg_type.c_param_type()
180 sep = ', '
bdd2d42b 181 elif arg_type:
48825ca4
EB
182 assert not arg_type.variants
183 for memb in arg_type.members:
184 ret += sep
185 sep = ', '
186 if memb.optional:
187 ret += 'bool has_%s, ' % c_name(memb.name)
188 ret += '%s %s' % (memb.type.c_param_type(),
189 c_name(memb.name))
03b4367a
MA
190 if extra:
191 ret += sep + extra
bdd2d42b 192 return ret if ret else 'void'
This page took 0.654137 seconds and 4 git commands to generate.