|
|
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):
134: return '_'.join(name.split('-')).lstrip("*")
135:
136: def c_list_type(name):
137: return '%sList' % name
138:
139: def type_name(name):
140: if type(name) == list:
141: return c_list_type(name[0])
142: return name
143:
144: enum_types = []
145:
146: def add_enum(name):
147: global enum_types
148: enum_types.append(name)
149:
150: def is_enum(name):
151: global enum_types
152: return (name in enum_types)
153:
154: def c_type(name):
155: if name == 'str':
156: return 'char *'
157: elif name == 'int':
158: return 'int64_t'
159: elif name == 'bool':
160: return 'bool'
161: elif name == 'number':
162: return 'double'
163: elif type(name) == list:
164: return '%s *' % c_list_type(name[0])
165: elif is_enum(name):
166: return name
167: elif name == None or len(name) == 0:
168: return 'void'
169: elif name == name.upper():
170: return '%sEvent *' % camel_case(name)
171: else:
172: return '%s *' % name
173:
174: def genindent(count):
175: ret = ""
176: for i in range(count):
177: ret += " "
178: return ret
179:
180: indent_level = 0
181:
182: def push_indent(indent_amount=4):
183: global indent_level
184: indent_level += indent_amount
185:
186: def pop_indent(indent_amount=4):
187: global indent_level
188: indent_level -= indent_amount
189:
190: def cgen(code, **kwds):
191: indent = genindent(indent_level)
192: lines = code.split('\n')
193: lines = map(lambda x: indent + x, lines)
194: return '\n'.join(lines) % kwds + '\n'
195:
196: def mcgen(code, **kwds):
197: return cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
198:
199: def basename(filename):
200: return filename.split("/")[-1]
201:
202: def guardname(filename):
203: return filename.replace("/", "_").replace("-", "_").split(".")[0].upper()
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.