|
|
1.1 root 1: #
2: # QAPI helper library
3: #
4: # Copyright IBM, Corp. 2011
5: #
6: # Authors:
7: # Anthony Liguori <[email protected]>
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:
12: from ordereddict import OrderedDict
13:
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
29:
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:]
37:
38: tokens = tokens[1:] # :
39:
40: value, tokens = parse(tokens)
41:
42: if tokens[0] == ',':
43: tokens = tokens[1:]
44:
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:]
60:
61: def evaluate(string):
62: return parse(map(lambda x: x, tokenize(string)))[0]
63:
64: def parse_schema(fp):
65: exprs = []
66: expr = ''
67: expr_eval = None
68:
69: for line in fp:
70: if line.startswith('#') or line == '\n':
71: continue
72:
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
85:
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)
93:
94: return exprs
95:
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)
108:
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
119:
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
132:
133: def c_var(name):
1.1.1.3 ! root 134: return name.replace('-', '_').lstrip("*")
! 135:
! 136: def c_fun(name):
! 137: return c_var(name).replace('.', '_')
1.1 root 138:
139: def c_list_type(name):
140: return '%sList' % name
141:
142: def type_name(name):
143: if type(name) == list:
144: return c_list_type(name[0])
145: return name
146:
147: enum_types = []
148:
149: def add_enum(name):
150: global enum_types
151: enum_types.append(name)
152:
153: def is_enum(name):
154: global enum_types
155: return (name in enum_types)
156:
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
176:
177: def genindent(count):
178: ret = ""
179: for i in range(count):
180: ret += " "
181: return ret
182:
183: indent_level = 0
184:
185: def push_indent(indent_amount=4):
186: global indent_level
187: indent_level += indent_amount
188:
189: def pop_indent(indent_amount=4):
190: global indent_level
191: indent_level -= indent_amount
192:
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'
198:
199: def mcgen(code, **kwds):
200: return cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
201:
202: def basename(filename):
203: return filename.split("/")[-1]
204:
205: def guardname(filename):
1.1.1.2 root 206: guard = basename(filename).rsplit(".", 1)[0]
207: for substr in [".", " ", "-"]:
208: guard = guard.replace(substr, "_")
209: return guard.upper() + '_H'
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.