]> git.proxmox.com Git - qemu.git/blobdiff - scripts/qapi.py
Merge git://github.com/hw-claudio/qemu-aarch64-queue into tcg-next
[qemu.git] / scripts / qapi.py
index e06233666b0f5de36ed6886d825af28f2e3fe035..baf13213a9afc4e83a1e7968d10f56ffb284e4e6 100644 (file)
 
 from ordereddict import OrderedDict
 
+builtin_types = [
+    'str', 'int', 'number', 'bool',
+    'int8', 'int16', 'int32', 'int64',
+    'uint8', 'uint16', 'uint32', 'uint64'
+]
+
 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:]
+        ch = data[0]
+        data = data[1:]
+        if ch in ['{', '}', ':', ',', '[', ']']:
+            yield ch
+        elif ch in ' \n':
+            None
+        elif ch == "'":
             string = ''
-            while data[0] != "'":
-                string += data[0]
+            esc = False
+            while True:
+                if (data == ''):
+                    raise Exception("Mismatched quotes")
+                ch = data[0]
                 data = data[1:]
-            data = data[1:]
+                if esc:
+                    string += ch
+                    esc = False
+                elif ch == "\\":
+                    esc = True
+                elif ch == "'":
+                    break
+                else:
+                    string += ch
             yield string
 
 def parse(tokens):
@@ -61,10 +78,8 @@ def parse(tokens):
 def evaluate(string):
     return parse(map(lambda x: x, tokenize(string)))[0]
 
-def parse_schema(fp):
-    exprs = []
+def get_expr(fp):
     expr = ''
-    expr_eval = None
 
     for line in fp:
         if line.startswith('#') or line == '\n':
@@ -73,27 +88,36 @@ def parse_schema(fp):
         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)
+            yield expr
             expr = line
         else:
             expr += line
 
     if expr:
+        yield expr
+
+def parse_schema(fp):
+    exprs = []
+
+    for expr in get_expr(fp):
         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'])
+        elif expr_eval.has_key('type'):
+            add_struct(expr_eval)
         exprs.append(expr_eval)
 
     return exprs
 
 def parse_args(typeinfo):
+    if isinstance(typeinfo, basestring):
+        struct = find_struct(typeinfo)
+        assert struct != None
+        typeinfo = struct['data']
+
     for member in typeinfo:
         argname = member
         argentry = typeinfo[member]
@@ -130,11 +154,29 @@ def camel_case(name):
             new_name += ch.lower()
     return new_name
 
-def c_var(name):
+def c_var(name, protect=True):
+    # ANSI X3J11/88-090, 3.1.1
+    c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
+                     'default', 'do', 'double', 'else', 'enum', 'extern', 'float',
+                     'for', 'goto', 'if', 'int', 'long', 'register', 'return',
+                     'short', 'signed', 'sizeof', 'static', 'struct', 'switch',
+                     'typedef', 'union', 'unsigned', 'void', 'volatile', 'while'])
+    # ISO/IEC 9899:1999, 6.4.1
+    c99_words = set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
+    # ISO/IEC 9899:2011, 6.4.1
+    c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic', '_Noreturn',
+                     '_Static_assert', '_Thread_local'])
+    # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
+    # excluding _.*
+    gcc_words = set(['asm', 'typeof'])
+    # namespace pollution:
+    polluted_words = set(['unix'])
+    if protect and (name in c89_words | c99_words | c11_words | gcc_words | polluted_words):
+        return "q_" + name
     return name.replace('-', '_').lstrip("*")
 
-def c_fun(name):
-    return c_var(name).replace('.', '_')
+def c_fun(name, protect=True):
+    return c_var(name, protect).replace('.', '_')
 
 def c_list_type(name):
     return '%sList' % name
@@ -145,6 +187,18 @@ def type_name(name):
     return name
 
 enum_types = []
+struct_types = []
+
+def add_struct(definition):
+    global struct_types
+    struct_types.append(definition)
+
+def find_struct(name):
+    global struct_types
+    for struct in struct_types:
+        if struct['type'] == name:
+            return struct
+    return None
 
 def add_enum(name):
     global enum_types
@@ -159,6 +213,12 @@ def c_type(name):
         return 'char *'
     elif name == 'int':
         return 'int64_t'
+    elif (name == 'int8' or name == 'int16' or name == 'int32' or
+          name == 'int64' or name == 'uint8' or name == 'uint16' or
+          name == 'uint32' or name == 'uint64'):
+        return name + '_t'
+    elif name == 'size':
+        return 'uint64_t'
     elif name == 'bool':
         return 'bool'
     elif name == 'number':
@@ -207,3 +267,20 @@ def guardname(filename):
     for substr in [".", " ", "-"]:
         guard = guard.replace(substr, "_")
     return guard.upper() + '_H'
+
+def guardstart(name):
+    return mcgen('''
+
+#ifndef %(name)s
+#define %(name)s
+
+''',
+                 name=guardname(name))
+
+def guardend(name):
+    return mcgen('''
+
+#endif /* %(name)s */
+
+''',
+                 name=guardname(name))