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