event_rpcgen.py revision 1.1 1 1.1 christos #!/usr/bin/env python2
2 1.1 christos #
3 1.1 christos # Copyright (c) 2005-2007 Niels Provos <provos (at] citi.umich.edu>
4 1.1 christos # Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
5 1.1 christos # All rights reserved.
6 1.1 christos #
7 1.1 christos # Generates marshaling code based on libevent.
8 1.1 christos
9 1.1 christos # TODO:
10 1.1 christos # 1) use optparse to allow the strategy shell to parse options, and
11 1.1 christos # to allow the instantiated factory (for the specific output language)
12 1.1 christos # to parse remaining options
13 1.1 christos # 2) move the globals into a class that manages execution (including the
14 1.1 christos # progress outputs that space stderr at the moment)
15 1.1 christos # 3) emit other languages
16 1.1 christos
17 1.1 christos import sys
18 1.1 christos import re
19 1.1 christos
20 1.1 christos _NAME = "event_rpcgen.py"
21 1.1 christos _VERSION = "0.1"
22 1.1 christos
23 1.1 christos # Globals
24 1.1 christos line_count = 0
25 1.1 christos
26 1.1 christos white = re.compile(r'\s+')
27 1.1 christos cppcomment = re.compile(r'\/\/.*$')
28 1.1 christos nonident = re.compile(r'[^a-zA-Z0-9_]')
29 1.1 christos structref = re.compile(r'^struct\[([a-zA-Z_][a-zA-Z0-9_]*)\]$')
30 1.1 christos structdef = re.compile(r'^struct +[a-zA-Z_][a-zA-Z0-9_]* *{$')
31 1.1 christos
32 1.1 christos headerdirect = []
33 1.1 christos cppdirect = []
34 1.1 christos
35 1.1 christos QUIETLY = 0
36 1.1 christos
37 1.1 christos def declare(s):
38 1.1 christos if not QUIETLY:
39 1.1 christos print s
40 1.1 christos
41 1.1 christos def TranslateList(mylist, mydict):
42 1.1 christos return map(lambda x: x % mydict, mylist)
43 1.1 christos
44 1.1 christos # Exception class for parse errors
45 1.1 christos class RpcGenError(Exception):
46 1.1 christos def __init__(self, why):
47 1.1 christos self.why = why
48 1.1 christos def __str__(self):
49 1.1 christos return str(self.why)
50 1.1 christos
51 1.1 christos # Holds everything that makes a struct
52 1.1 christos class Struct:
53 1.1 christos def __init__(self, name):
54 1.1 christos self._name = name
55 1.1 christos self._entries = []
56 1.1 christos self._tags = {}
57 1.1 christos declare(' Created struct: %s' % name)
58 1.1 christos
59 1.1 christos def AddEntry(self, entry):
60 1.1 christos if self._tags.has_key(entry.Tag()):
61 1.1 christos raise RpcGenError(
62 1.1 christos 'Entry "%s" duplicates tag number %d from "%s" '
63 1.1 christos 'around line %d' % (entry.Name(), entry.Tag(),
64 1.1 christos self._tags[entry.Tag()], line_count))
65 1.1 christos self._entries.append(entry)
66 1.1 christos self._tags[entry.Tag()] = entry.Name()
67 1.1 christos declare(' Added entry: %s' % entry.Name())
68 1.1 christos
69 1.1 christos def Name(self):
70 1.1 christos return self._name
71 1.1 christos
72 1.1 christos def EntryTagName(self, entry):
73 1.1 christos """Creates the name inside an enumeration for distinguishing data
74 1.1 christos types."""
75 1.1 christos name = "%s_%s" % (self._name, entry.Name())
76 1.1 christos return name.upper()
77 1.1 christos
78 1.1 christos def PrintIndented(self, file, ident, code):
79 1.1 christos """Takes an array, add indentation to each entry and prints it."""
80 1.1 christos for entry in code:
81 1.1 christos print >>file, '%s%s' % (ident, entry)
82 1.1 christos
83 1.1 christos class StructCCode(Struct):
84 1.1 christos """ Knows how to generate C code for a struct """
85 1.1 christos
86 1.1 christos def __init__(self, name):
87 1.1 christos Struct.__init__(self, name)
88 1.1 christos
89 1.1 christos def PrintTags(self, file):
90 1.1 christos """Prints the tag definitions for a structure."""
91 1.1 christos print >>file, '/* Tag definition for %s */' % self._name
92 1.1 christos print >>file, 'enum %s_ {' % self._name.lower()
93 1.1 christos for entry in self._entries:
94 1.1 christos print >>file, ' %s=%d,' % (self.EntryTagName(entry),
95 1.1 christos entry.Tag())
96 1.1 christos print >>file, ' %s_MAX_TAGS' % (self._name.upper())
97 1.1 christos print >>file, '};\n'
98 1.1 christos
99 1.1 christos def PrintForwardDeclaration(self, file):
100 1.1 christos print >>file, 'struct %s;' % self._name
101 1.1 christos
102 1.1 christos def PrintDeclaration(self, file):
103 1.1 christos print >>file, '/* Structure declaration for %s */' % self._name
104 1.1 christos print >>file, 'struct %s_access_ {' % self._name
105 1.1 christos for entry in self._entries:
106 1.1 christos dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name())
107 1.1 christos dcl.extend(
108 1.1 christos entry.GetDeclaration('(*%s_get)' % entry.Name()))
109 1.1 christos if entry.Array():
110 1.1 christos dcl.extend(
111 1.1 christos entry.AddDeclaration('(*%s_add)' % entry.Name()))
112 1.1 christos self.PrintIndented(file, ' ', dcl)
113 1.1 christos print >>file, '};\n'
114 1.1 christos
115 1.1 christos print >>file, 'struct %s {' % self._name
116 1.1 christos print >>file, ' struct %s_access_ *base;\n' % self._name
117 1.1 christos for entry in self._entries:
118 1.1 christos dcl = entry.Declaration()
119 1.1 christos self.PrintIndented(file, ' ', dcl)
120 1.1 christos print >>file, ''
121 1.1 christos for entry in self._entries:
122 1.1 christos print >>file, ' ev_uint8_t %s_set;' % entry.Name()
123 1.1 christos print >>file, '};\n'
124 1.1 christos
125 1.1 christos print >>file, \
126 1.1 christos """struct %(name)s *%(name)s_new(void);
127 1.1 christos struct %(name)s *%(name)s_new_with_arg(void *);
128 1.1 christos void %(name)s_free(struct %(name)s *);
129 1.1 christos void %(name)s_clear(struct %(name)s *);
130 1.1 christos void %(name)s_marshal(struct evbuffer *, const struct %(name)s *);
131 1.1 christos int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *);
132 1.1 christos int %(name)s_complete(struct %(name)s *);
133 1.1 christos void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t,
134 1.1 christos const struct %(name)s *);
135 1.1 christos int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
136 1.1 christos struct %(name)s *);""" % { 'name' : self._name }
137 1.1 christos
138 1.1 christos
139 1.1 christos # Write a setting function of every variable
140 1.1 christos for entry in self._entries:
141 1.1 christos self.PrintIndented(file, '', entry.AssignDeclaration(
142 1.1 christos entry.AssignFuncName()))
143 1.1 christos self.PrintIndented(file, '', entry.GetDeclaration(
144 1.1 christos entry.GetFuncName()))
145 1.1 christos if entry.Array():
146 1.1 christos self.PrintIndented(file, '', entry.AddDeclaration(
147 1.1 christos entry.AddFuncName()))
148 1.1 christos
149 1.1 christos print >>file, '/* --- %s done --- */\n' % self._name
150 1.1 christos
151 1.1 christos def PrintCode(self, file):
152 1.1 christos print >>file, ('/*\n'
153 1.1 christos ' * Implementation of %s\n'
154 1.1 christos ' */\n') % self._name
155 1.1 christos
156 1.1 christos print >>file, \
157 1.1 christos 'static struct %(name)s_access_ %(name)s_base__ = {' % \
158 1.1 christos { 'name' : self._name }
159 1.1 christos for entry in self._entries:
160 1.1 christos self.PrintIndented(file, ' ', entry.CodeBase())
161 1.1 christos print >>file, '};\n'
162 1.1 christos
163 1.1 christos # Creation
164 1.1 christos print >>file, (
165 1.1 christos 'struct %(name)s *\n'
166 1.1 christos '%(name)s_new(void)\n'
167 1.1 christos '{\n'
168 1.1 christos ' return %(name)s_new_with_arg(NULL);\n'
169 1.1 christos '}\n'
170 1.1 christos '\n'
171 1.1 christos 'struct %(name)s *\n'
172 1.1 christos '%(name)s_new_with_arg(void *unused)\n'
173 1.1 christos '{\n'
174 1.1 christos ' struct %(name)s *tmp;\n'
175 1.1 christos ' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n'
176 1.1 christos ' event_warn("%%s: malloc", __func__);\n'
177 1.1 christos ' return (NULL);\n'
178 1.1 christos ' }\n'
179 1.1 christos ' tmp->base = &%(name)s_base__;\n') % { 'name' : self._name }
180 1.1 christos
181 1.1 christos for entry in self._entries:
182 1.1 christos self.PrintIndented(file, ' ', entry.CodeInitialize('tmp'))
183 1.1 christos print >>file, ' tmp->%s_set = 0;\n' % entry.Name()
184 1.1 christos
185 1.1 christos print >>file, (
186 1.1 christos ' return (tmp);\n'
187 1.1 christos '}\n')
188 1.1 christos
189 1.1 christos # Adding
190 1.1 christos for entry in self._entries:
191 1.1 christos if entry.Array():
192 1.1 christos self.PrintIndented(file, '', entry.CodeAdd())
193 1.1 christos print >>file, ''
194 1.1 christos
195 1.1 christos # Assigning
196 1.1 christos for entry in self._entries:
197 1.1 christos self.PrintIndented(file, '', entry.CodeAssign())
198 1.1 christos print >>file, ''
199 1.1 christos
200 1.1 christos # Getting
201 1.1 christos for entry in self._entries:
202 1.1 christos self.PrintIndented(file, '', entry.CodeGet())
203 1.1 christos print >>file, ''
204 1.1 christos
205 1.1 christos # Clearing
206 1.1 christos print >>file, ( 'void\n'
207 1.1 christos '%(name)s_clear(struct %(name)s *tmp)\n'
208 1.1 christos '{'
209 1.1 christos ) % { 'name' : self._name }
210 1.1 christos for entry in self._entries:
211 1.1 christos self.PrintIndented(file, ' ', entry.CodeClear('tmp'))
212 1.1 christos
213 1.1 christos print >>file, '}\n'
214 1.1 christos
215 1.1 christos # Freeing
216 1.1 christos print >>file, ( 'void\n'
217 1.1 christos '%(name)s_free(struct %(name)s *tmp)\n'
218 1.1 christos '{'
219 1.1 christos ) % { 'name' : self._name }
220 1.1 christos
221 1.1 christos for entry in self._entries:
222 1.1 christos self.PrintIndented(file, ' ', entry.CodeFree('tmp'))
223 1.1 christos
224 1.1 christos print >>file, (' free(tmp);\n'
225 1.1 christos '}\n')
226 1.1 christos
227 1.1 christos # Marshaling
228 1.1 christos print >>file, ('void\n'
229 1.1 christos '%(name)s_marshal(struct evbuffer *evbuf, '
230 1.1 christos 'const struct %(name)s *tmp)'
231 1.1 christos '{') % { 'name' : self._name }
232 1.1 christos for entry in self._entries:
233 1.1 christos indent = ' '
234 1.1 christos # Optional entries do not have to be set
235 1.1 christos if entry.Optional():
236 1.1 christos indent += ' '
237 1.1 christos print >>file, ' if (tmp->%s_set) {' % entry.Name()
238 1.1 christos self.PrintIndented(
239 1.1 christos file, indent,
240 1.1 christos entry.CodeMarshal('evbuf', self.EntryTagName(entry),
241 1.1 christos entry.GetVarName('tmp'),
242 1.1 christos entry.GetVarLen('tmp')))
243 1.1 christos if entry.Optional():
244 1.1 christos print >>file, ' }'
245 1.1 christos
246 1.1 christos print >>file, '}\n'
247 1.1 christos
248 1.1 christos # Unmarshaling
249 1.1 christos print >>file, ('int\n'
250 1.1 christos '%(name)s_unmarshal(struct %(name)s *tmp, '
251 1.1 christos ' struct evbuffer *evbuf)\n'
252 1.1 christos '{\n'
253 1.1 christos ' ev_uint32_t tag;\n'
254 1.1 christos ' while (evbuffer_get_length(evbuf) > 0) {\n'
255 1.1 christos ' if (evtag_peek(evbuf, &tag) == -1)\n'
256 1.1 christos ' return (-1);\n'
257 1.1 christos ' switch (tag) {\n'
258 1.1 christos ) % { 'name' : self._name }
259 1.1 christos for entry in self._entries:
260 1.1 christos print >>file, ' case %s:\n' % self.EntryTagName(entry)
261 1.1 christos if not entry.Array():
262 1.1 christos print >>file, (
263 1.1 christos ' if (tmp->%s_set)\n'
264 1.1 christos ' return (-1);'
265 1.1 christos ) % (entry.Name())
266 1.1 christos
267 1.1 christos self.PrintIndented(
268 1.1 christos file, ' ',
269 1.1 christos entry.CodeUnmarshal('evbuf',
270 1.1 christos self.EntryTagName(entry),
271 1.1 christos entry.GetVarName('tmp'),
272 1.1 christos entry.GetVarLen('tmp')))
273 1.1 christos
274 1.1 christos print >>file, ( ' tmp->%s_set = 1;\n' % entry.Name() +
275 1.1 christos ' break;\n' )
276 1.1 christos print >>file, ( ' default:\n'
277 1.1 christos ' return -1;\n'
278 1.1 christos ' }\n'
279 1.1 christos ' }\n' )
280 1.1 christos # Check if it was decoded completely
281 1.1 christos print >>file, ( ' if (%(name)s_complete(tmp) == -1)\n'
282 1.1 christos ' return (-1);'
283 1.1 christos ) % { 'name' : self._name }
284 1.1 christos
285 1.1 christos # Successfully decoded
286 1.1 christos print >>file, ( ' return (0);\n'
287 1.1 christos '}\n')
288 1.1 christos
289 1.1 christos # Checking if a structure has all the required data
290 1.1 christos print >>file, (
291 1.1 christos 'int\n'
292 1.1 christos '%(name)s_complete(struct %(name)s *msg)\n'
293 1.1 christos '{' ) % { 'name' : self._name }
294 1.1 christos for entry in self._entries:
295 1.1 christos if not entry.Optional():
296 1.1 christos code = [
297 1.1 christos 'if (!msg->%(name)s_set)',
298 1.1 christos ' return (-1);' ]
299 1.1 christos code = TranslateList(code, entry.GetTranslation())
300 1.1 christos self.PrintIndented(
301 1.1 christos file, ' ', code)
302 1.1 christos
303 1.1 christos self.PrintIndented(
304 1.1 christos file, ' ',
305 1.1 christos entry.CodeComplete('msg', entry.GetVarName('msg')))
306 1.1 christos print >>file, (
307 1.1 christos ' return (0);\n'
308 1.1 christos '}\n' )
309 1.1 christos
310 1.1 christos # Complete message unmarshaling
311 1.1 christos print >>file, (
312 1.1 christos 'int\n'
313 1.1 christos 'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, '
314 1.1 christos 'ev_uint32_t need_tag, struct %(name)s *msg)\n'
315 1.1 christos '{\n'
316 1.1 christos ' ev_uint32_t tag;\n'
317 1.1 christos ' int res = -1;\n'
318 1.1 christos '\n'
319 1.1 christos ' struct evbuffer *tmp = evbuffer_new();\n'
320 1.1 christos '\n'
321 1.1 christos ' if (evtag_unmarshal(evbuf, &tag, tmp) == -1'
322 1.1 christos ' || tag != need_tag)\n'
323 1.1 christos ' goto error;\n'
324 1.1 christos '\n'
325 1.1 christos ' if (%(name)s_unmarshal(msg, tmp) == -1)\n'
326 1.1 christos ' goto error;\n'
327 1.1 christos '\n'
328 1.1 christos ' res = 0;\n'
329 1.1 christos '\n'
330 1.1 christos ' error:\n'
331 1.1 christos ' evbuffer_free(tmp);\n'
332 1.1 christos ' return (res);\n'
333 1.1 christos '}\n' ) % { 'name' : self._name }
334 1.1 christos
335 1.1 christos # Complete message marshaling
336 1.1 christos print >>file, (
337 1.1 christos 'void\n'
338 1.1 christos 'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, '
339 1.1 christos 'const struct %(name)s *msg)\n'
340 1.1 christos '{\n'
341 1.1 christos ' struct evbuffer *buf_ = evbuffer_new();\n'
342 1.1 christos ' assert(buf_ != NULL);\n'
343 1.1 christos ' %(name)s_marshal(buf_, msg);\n'
344 1.1 christos ' evtag_marshal_buffer(evbuf, tag, buf_);\n '
345 1.1 christos ' evbuffer_free(buf_);\n'
346 1.1 christos '}\n' ) % { 'name' : self._name }
347 1.1 christos
348 1.1 christos class Entry:
349 1.1 christos def __init__(self, type, name, tag):
350 1.1 christos self._type = type
351 1.1 christos self._name = name
352 1.1 christos self._tag = int(tag)
353 1.1 christos self._ctype = type
354 1.1 christos self._optional = 0
355 1.1 christos self._can_be_array = 0
356 1.1 christos self._array = 0
357 1.1 christos self._line_count = -1
358 1.1 christos self._struct = None
359 1.1 christos self._refname = None
360 1.1 christos
361 1.1 christos self._optpointer = True
362 1.1 christos self._optaddarg = True
363 1.1 christos
364 1.1 christos def GetInitializer(self):
365 1.1 christos assert 0, "Entry does not provide initializer"
366 1.1 christos
367 1.1 christos def SetStruct(self, struct):
368 1.1 christos self._struct = struct
369 1.1 christos
370 1.1 christos def LineCount(self):
371 1.1 christos assert self._line_count != -1
372 1.1 christos return self._line_count
373 1.1 christos
374 1.1 christos def SetLineCount(self, number):
375 1.1 christos self._line_count = number
376 1.1 christos
377 1.1 christos def Array(self):
378 1.1 christos return self._array
379 1.1 christos
380 1.1 christos def Optional(self):
381 1.1 christos return self._optional
382 1.1 christos
383 1.1 christos def Tag(self):
384 1.1 christos return self._tag
385 1.1 christos
386 1.1 christos def Name(self):
387 1.1 christos return self._name
388 1.1 christos
389 1.1 christos def Type(self):
390 1.1 christos return self._type
391 1.1 christos
392 1.1 christos def MakeArray(self, yes=1):
393 1.1 christos self._array = yes
394 1.1 christos
395 1.1 christos def MakeOptional(self):
396 1.1 christos self._optional = 1
397 1.1 christos
398 1.1 christos def Verify(self):
399 1.1 christos if self.Array() and not self._can_be_array:
400 1.1 christos raise RpcGenError(
401 1.1 christos 'Entry "%s" cannot be created as an array '
402 1.1 christos 'around line %d' % (self._name, self.LineCount()))
403 1.1 christos if not self._struct:
404 1.1 christos raise RpcGenError(
405 1.1 christos 'Entry "%s" does not know which struct it belongs to '
406 1.1 christos 'around line %d' % (self._name, self.LineCount()))
407 1.1 christos if self._optional and self._array:
408 1.1 christos raise RpcGenError(
409 1.1 christos 'Entry "%s" has illegal combination of optional and array '
410 1.1 christos 'around line %d' % (self._name, self.LineCount()))
411 1.1 christos
412 1.1 christos def GetTranslation(self, extradict = {}):
413 1.1 christos mapping = {
414 1.1 christos "parent_name" : self._struct.Name(),
415 1.1 christos "name" : self._name,
416 1.1 christos "ctype" : self._ctype,
417 1.1 christos "refname" : self._refname,
418 1.1 christos "optpointer" : self._optpointer and "*" or "",
419 1.1 christos "optreference" : self._optpointer and "&" or "",
420 1.1 christos "optaddarg" :
421 1.1 christos self._optaddarg and ", const %s value" % self._ctype or ""
422 1.1 christos }
423 1.1 christos for (k, v) in extradict.items():
424 1.1 christos mapping[k] = v
425 1.1 christos
426 1.1 christos return mapping
427 1.1 christos
428 1.1 christos def GetVarName(self, var):
429 1.1 christos return '%(var)s->%(name)s_data' % self.GetTranslation({ 'var' : var })
430 1.1 christos
431 1.1 christos def GetVarLen(self, var):
432 1.1 christos return 'sizeof(%s)' % self._ctype
433 1.1 christos
434 1.1 christos def GetFuncName(self):
435 1.1 christos return '%s_%s_get' % (self._struct.Name(), self._name)
436 1.1 christos
437 1.1 christos def GetDeclaration(self, funcname):
438 1.1 christos code = [ 'int %s(struct %s *, %s *);' % (
439 1.1 christos funcname, self._struct.Name(), self._ctype ) ]
440 1.1 christos return code
441 1.1 christos
442 1.1 christos def CodeGet(self):
443 1.1 christos code = (
444 1.1 christos 'int',
445 1.1 christos '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, '
446 1.1 christos '%(ctype)s *value)',
447 1.1 christos '{',
448 1.1 christos ' if (msg->%(name)s_set != 1)',
449 1.1 christos ' return (-1);',
450 1.1 christos ' *value = msg->%(name)s_data;',
451 1.1 christos ' return (0);',
452 1.1 christos '}' )
453 1.1 christos code = '\n'.join(code)
454 1.1 christos code = code % self.GetTranslation()
455 1.1 christos return code.split('\n')
456 1.1 christos
457 1.1 christos def AssignFuncName(self):
458 1.1 christos return '%s_%s_assign' % (self._struct.Name(), self._name)
459 1.1 christos
460 1.1 christos def AddFuncName(self):
461 1.1 christos return '%s_%s_add' % (self._struct.Name(), self._name)
462 1.1 christos
463 1.1 christos def AssignDeclaration(self, funcname):
464 1.1 christos code = [ 'int %s(struct %s *, const %s);' % (
465 1.1 christos funcname, self._struct.Name(), self._ctype ) ]
466 1.1 christos return code
467 1.1 christos
468 1.1 christos def CodeAssign(self):
469 1.1 christos code = [ 'int',
470 1.1 christos '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,'
471 1.1 christos ' const %(ctype)s value)',
472 1.1 christos '{',
473 1.1 christos ' msg->%(name)s_set = 1;',
474 1.1 christos ' msg->%(name)s_data = value;',
475 1.1 christos ' return (0);',
476 1.1 christos '}' ]
477 1.1 christos code = '\n'.join(code)
478 1.1 christos code = code % self.GetTranslation()
479 1.1 christos return code.split('\n')
480 1.1 christos
481 1.1 christos def CodeClear(self, structname):
482 1.1 christos code = [ '%s->%s_set = 0;' % (structname, self.Name()) ]
483 1.1 christos
484 1.1 christos return code
485 1.1 christos
486 1.1 christos def CodeComplete(self, structname, var_name):
487 1.1 christos return []
488 1.1 christos
489 1.1 christos def CodeFree(self, name):
490 1.1 christos return []
491 1.1 christos
492 1.1 christos def CodeBase(self):
493 1.1 christos code = [
494 1.1 christos '%(parent_name)s_%(name)s_assign,',
495 1.1 christos '%(parent_name)s_%(name)s_get,'
496 1.1 christos ]
497 1.1 christos if self.Array():
498 1.1 christos code.append('%(parent_name)s_%(name)s_add,')
499 1.1 christos
500 1.1 christos code = '\n'.join(code)
501 1.1 christos code = code % self.GetTranslation()
502 1.1 christos return code.split('\n')
503 1.1 christos
504 1.1 christos class EntryBytes(Entry):
505 1.1 christos def __init__(self, type, name, tag, length):
506 1.1 christos # Init base class
507 1.1 christos Entry.__init__(self, type, name, tag)
508 1.1 christos
509 1.1 christos self._length = length
510 1.1 christos self._ctype = 'ev_uint8_t'
511 1.1 christos
512 1.1 christos def GetInitializer(self):
513 1.1 christos return "NULL"
514 1.1 christos
515 1.1 christos def GetVarLen(self, var):
516 1.1 christos return '(%s)' % self._length
517 1.1 christos
518 1.1 christos def CodeArrayAdd(self, varname, value):
519 1.1 christos # XXX: copy here
520 1.1 christos return [ '%(varname)s = NULL;' % { 'varname' : varname } ]
521 1.1 christos
522 1.1 christos def GetDeclaration(self, funcname):
523 1.1 christos code = [ 'int %s(struct %s *, %s **);' % (
524 1.1 christos funcname, self._struct.Name(), self._ctype ) ]
525 1.1 christos return code
526 1.1 christos
527 1.1 christos def AssignDeclaration(self, funcname):
528 1.1 christos code = [ 'int %s(struct %s *, const %s *);' % (
529 1.1 christos funcname, self._struct.Name(), self._ctype ) ]
530 1.1 christos return code
531 1.1 christos
532 1.1 christos def Declaration(self):
533 1.1 christos dcl = ['ev_uint8_t %s_data[%s];' % (self._name, self._length)]
534 1.1 christos
535 1.1 christos return dcl
536 1.1 christos
537 1.1 christos def CodeGet(self):
538 1.1 christos name = self._name
539 1.1 christos code = [ 'int',
540 1.1 christos '%s_%s_get(struct %s *msg, %s **value)' % (
541 1.1 christos self._struct.Name(), name,
542 1.1 christos self._struct.Name(), self._ctype),
543 1.1 christos '{',
544 1.1 christos ' if (msg->%s_set != 1)' % name,
545 1.1 christos ' return (-1);',
546 1.1 christos ' *value = msg->%s_data;' % name,
547 1.1 christos ' return (0);',
548 1.1 christos '}' ]
549 1.1 christos return code
550 1.1 christos
551 1.1 christos def CodeAssign(self):
552 1.1 christos name = self._name
553 1.1 christos code = [ 'int',
554 1.1 christos '%s_%s_assign(struct %s *msg, const %s *value)' % (
555 1.1 christos self._struct.Name(), name,
556 1.1 christos self._struct.Name(), self._ctype),
557 1.1 christos '{',
558 1.1 christos ' msg->%s_set = 1;' % name,
559 1.1 christos ' memcpy(msg->%s_data, value, %s);' % (
560 1.1 christos name, self._length),
561 1.1 christos ' return (0);',
562 1.1 christos '}' ]
563 1.1 christos return code
564 1.1 christos
565 1.1 christos def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
566 1.1 christos code = [ 'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, '
567 1.1 christos '%(var)s, %(varlen)s) == -1) {',
568 1.1 christos ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
569 1.1 christos ' return (-1);',
570 1.1 christos '}'
571 1.1 christos ]
572 1.1 christos return TranslateList(code,
573 1.1 christos self.GetTranslation({
574 1.1 christos 'var' : var_name,
575 1.1 christos 'varlen' : var_len,
576 1.1 christos 'buf' : buf,
577 1.1 christos 'tag' : tag_name }))
578 1.1 christos
579 1.1 christos def CodeMarshal(self, buf, tag_name, var_name, var_len):
580 1.1 christos code = ['evtag_marshal(%s, %s, %s, %s);' % (
581 1.1 christos buf, tag_name, var_name, var_len)]
582 1.1 christos return code
583 1.1 christos
584 1.1 christos def CodeClear(self, structname):
585 1.1 christos code = [ '%s->%s_set = 0;' % (structname, self.Name()),
586 1.1 christos 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
587 1.1 christos structname, self._name, structname, self._name)]
588 1.1 christos
589 1.1 christos return code
590 1.1 christos
591 1.1 christos def CodeInitialize(self, name):
592 1.1 christos code = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
593 1.1 christos name, self._name, name, self._name)]
594 1.1 christos return code
595 1.1 christos
596 1.1 christos def Verify(self):
597 1.1 christos if not self._length:
598 1.1 christos raise RpcGenError(
599 1.1 christos 'Entry "%s" needs a length '
600 1.1 christos 'around line %d' % (self._name, self.LineCount()))
601 1.1 christos
602 1.1 christos Entry.Verify(self)
603 1.1 christos
604 1.1 christos class EntryInt(Entry):
605 1.1 christos def __init__(self, type, name, tag, bits=32):
606 1.1 christos # Init base class
607 1.1 christos Entry.__init__(self, type, name, tag)
608 1.1 christos
609 1.1 christos self._can_be_array = 1
610 1.1 christos if bits == 32:
611 1.1 christos self._ctype = 'ev_uint32_t'
612 1.1 christos self._marshal_type = 'int'
613 1.1 christos if bits == 64:
614 1.1 christos self._ctype = 'ev_uint64_t'
615 1.1 christos self._marshal_type = 'int64'
616 1.1 christos
617 1.1 christos def GetInitializer(self):
618 1.1 christos return "0"
619 1.1 christos
620 1.1 christos def CodeArrayFree(self, var):
621 1.1 christos return []
622 1.1 christos
623 1.1 christos def CodeArrayAssign(self, varname, srcvar):
624 1.1 christos return [ '%(varname)s = %(srcvar)s;' % { 'varname' : varname,
625 1.1 christos 'srcvar' : srcvar } ]
626 1.1 christos
627 1.1 christos def CodeArrayAdd(self, varname, value):
628 1.1 christos """Returns a new entry of this type."""
629 1.1 christos return [ '%(varname)s = %(value)s;' % { 'varname' : varname,
630 1.1 christos 'value' : value } ]
631 1.1 christos
632 1.1 christos def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
633 1.1 christos code = [
634 1.1 christos 'if (evtag_unmarshal_%(ma)s(%(buf)s, %(tag)s, &%(var)s) == -1) {',
635 1.1 christos ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
636 1.1 christos ' return (-1);',
637 1.1 christos '}' ]
638 1.1 christos code = '\n'.join(code) % self.GetTranslation({
639 1.1 christos 'ma' : self._marshal_type,
640 1.1 christos 'buf' : buf,
641 1.1 christos 'tag' : tag_name,
642 1.1 christos 'var' : var_name })
643 1.1 christos return code.split('\n')
644 1.1 christos
645 1.1 christos def CodeMarshal(self, buf, tag_name, var_name, var_len):
646 1.1 christos code = [
647 1.1 christos 'evtag_marshal_%s(%s, %s, %s);' % (
648 1.1 christos self._marshal_type, buf, tag_name, var_name)]
649 1.1 christos return code
650 1.1 christos
651 1.1 christos def Declaration(self):
652 1.1 christos dcl = ['%s %s_data;' % (self._ctype, self._name)]
653 1.1 christos
654 1.1 christos return dcl
655 1.1 christos
656 1.1 christos def CodeInitialize(self, name):
657 1.1 christos code = ['%s->%s_data = 0;' % (name, self._name)]
658 1.1 christos return code
659 1.1 christos
660 1.1 christos class EntryString(Entry):
661 1.1 christos def __init__(self, type, name, tag):
662 1.1 christos # Init base class
663 1.1 christos Entry.__init__(self, type, name, tag)
664 1.1 christos
665 1.1 christos self._can_be_array = 1
666 1.1 christos self._ctype = 'char *'
667 1.1 christos
668 1.1 christos def GetInitializer(self):
669 1.1 christos return "NULL"
670 1.1 christos
671 1.1 christos def CodeArrayFree(self, varname):
672 1.1 christos code = [
673 1.1 christos 'if (%(var)s != NULL) free(%(var)s);' ]
674 1.1 christos
675 1.1 christos return TranslateList(code, { 'var' : varname })
676 1.1 christos
677 1.1 christos def CodeArrayAssign(self, varname, srcvar):
678 1.1 christos code = [
679 1.1 christos 'if (%(var)s != NULL)',
680 1.1 christos ' free(%(var)s);',
681 1.1 christos '%(var)s = strdup(%(srcvar)s);',
682 1.1 christos 'if (%(var)s == NULL) {',
683 1.1 christos ' event_warnx("%%s: strdup", __func__);',
684 1.1 christos ' return (-1);',
685 1.1 christos '}' ]
686 1.1 christos
687 1.1 christos return TranslateList(code, { 'var' : varname,
688 1.1 christos 'srcvar' : srcvar })
689 1.1 christos
690 1.1 christos def CodeArrayAdd(self, varname, value):
691 1.1 christos code = [
692 1.1 christos 'if (%(value)s != NULL) {',
693 1.1 christos ' %(var)s = strdup(%(value)s);',
694 1.1 christos ' if (%(var)s == NULL) {',
695 1.1 christos ' goto error;',
696 1.1 christos ' }',
697 1.1 christos '} else {',
698 1.1 christos ' %(var)s = NULL;',
699 1.1 christos '}' ]
700 1.1 christos
701 1.1 christos return TranslateList(code, { 'var' : varname,
702 1.1 christos 'value' : value })
703 1.1 christos
704 1.1 christos def GetVarLen(self, var):
705 1.1 christos return 'strlen(%s)' % self.GetVarName(var)
706 1.1 christos
707 1.1 christos def CodeMakeInitalize(self, varname):
708 1.1 christos return '%(varname)s = NULL;' % { 'varname' : varname }
709 1.1 christos
710 1.1 christos def CodeAssign(self):
711 1.1 christos name = self._name
712 1.1 christos code = """int
713 1.1 christos %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
714 1.1 christos const %(ctype)s value)
715 1.1 christos {
716 1.1 christos if (msg->%(name)s_data != NULL)
717 1.1 christos free(msg->%(name)s_data);
718 1.1 christos if ((msg->%(name)s_data = strdup(value)) == NULL)
719 1.1 christos return (-1);
720 1.1 christos msg->%(name)s_set = 1;
721 1.1 christos return (0);
722 1.1 christos }""" % self.GetTranslation()
723 1.1 christos
724 1.1 christos return code.split('\n')
725 1.1 christos
726 1.1 christos def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
727 1.1 christos code = ['if (evtag_unmarshal_string(%(buf)s, %(tag)s, &%(var)s) == -1) {',
728 1.1 christos ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
729 1.1 christos ' return (-1);',
730 1.1 christos '}'
731 1.1 christos ]
732 1.1 christos code = '\n'.join(code) % self.GetTranslation({
733 1.1 christos 'buf' : buf,
734 1.1 christos 'tag' : tag_name,
735 1.1 christos 'var' : var_name })
736 1.1 christos return code.split('\n')
737 1.1 christos
738 1.1 christos def CodeMarshal(self, buf, tag_name, var_name, var_len):
739 1.1 christos code = ['evtag_marshal_string(%s, %s, %s);' % (
740 1.1 christos buf, tag_name, var_name)]
741 1.1 christos return code
742 1.1 christos
743 1.1 christos def CodeClear(self, structname):
744 1.1 christos code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
745 1.1 christos ' free(%s->%s_data);' % (structname, self.Name()),
746 1.1 christos ' %s->%s_data = NULL;' % (structname, self.Name()),
747 1.1 christos ' %s->%s_set = 0;' % (structname, self.Name()),
748 1.1 christos '}'
749 1.1 christos ]
750 1.1 christos
751 1.1 christos return code
752 1.1 christos
753 1.1 christos def CodeInitialize(self, name):
754 1.1 christos code = ['%s->%s_data = NULL;' % (name, self._name)]
755 1.1 christos return code
756 1.1 christos
757 1.1 christos def CodeFree(self, name):
758 1.1 christos code = ['if (%s->%s_data != NULL)' % (name, self._name),
759 1.1 christos ' free (%s->%s_data);' % (name, self._name)]
760 1.1 christos
761 1.1 christos return code
762 1.1 christos
763 1.1 christos def Declaration(self):
764 1.1 christos dcl = ['char *%s_data;' % self._name]
765 1.1 christos
766 1.1 christos return dcl
767 1.1 christos
768 1.1 christos class EntryStruct(Entry):
769 1.1 christos def __init__(self, type, name, tag, refname):
770 1.1 christos # Init base class
771 1.1 christos Entry.__init__(self, type, name, tag)
772 1.1 christos
773 1.1 christos self._optpointer = False
774 1.1 christos self._can_be_array = 1
775 1.1 christos self._refname = refname
776 1.1 christos self._ctype = 'struct %s*' % refname
777 1.1 christos self._optaddarg = False
778 1.1 christos
779 1.1 christos def GetInitializer(self):
780 1.1 christos return "NULL"
781 1.1 christos
782 1.1 christos def GetVarLen(self, var):
783 1.1 christos return '-1'
784 1.1 christos
785 1.1 christos def CodeArrayAdd(self, varname, value):
786 1.1 christos code = [
787 1.1 christos '%(varname)s = %(refname)s_new();',
788 1.1 christos 'if (%(varname)s == NULL)',
789 1.1 christos ' goto error;' ]
790 1.1 christos
791 1.1 christos return TranslateList(code, self.GetTranslation({ 'varname' : varname }))
792 1.1 christos
793 1.1 christos def CodeArrayFree(self, var):
794 1.1 christos code = [ '%(refname)s_free(%(var)s);' % self.GetTranslation(
795 1.1 christos { 'var' : var }) ]
796 1.1 christos return code
797 1.1 christos
798 1.1 christos def CodeArrayAssign(self, var, srcvar):
799 1.1 christos code = [
800 1.1 christos 'int had_error = 0;',
801 1.1 christos 'struct evbuffer *tmp = NULL;',
802 1.1 christos '%(refname)s_clear(%(var)s);',
803 1.1 christos 'if ((tmp = evbuffer_new()) == NULL) {',
804 1.1 christos ' event_warn("%%s: evbuffer_new()", __func__);',
805 1.1 christos ' had_error = 1;',
806 1.1 christos ' goto done;',
807 1.1 christos '}',
808 1.1 christos '%(refname)s_marshal(tmp, %(srcvar)s);',
809 1.1 christos 'if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {',
810 1.1 christos ' event_warnx("%%s: %(refname)s_unmarshal", __func__);',
811 1.1 christos ' had_error = 1;',
812 1.1 christos ' goto done;',
813 1.1 christos '}',
814 1.1 christos 'done:'
815 1.1 christos 'if (tmp != NULL)',
816 1.1 christos ' evbuffer_free(tmp);',
817 1.1 christos 'if (had_error) {',
818 1.1 christos ' %(refname)s_clear(%(var)s);',
819 1.1 christos ' return (-1);',
820 1.1 christos '}' ]
821 1.1 christos
822 1.1 christos return TranslateList(code, self.GetTranslation({
823 1.1 christos 'var' : var,
824 1.1 christos 'srcvar' : srcvar}))
825 1.1 christos
826 1.1 christos def CodeGet(self):
827 1.1 christos name = self._name
828 1.1 christos code = [ 'int',
829 1.1 christos '%s_%s_get(struct %s *msg, %s *value)' % (
830 1.1 christos self._struct.Name(), name,
831 1.1 christos self._struct.Name(), self._ctype),
832 1.1 christos '{',
833 1.1 christos ' if (msg->%s_set != 1) {' % name,
834 1.1 christos ' msg->%s_data = %s_new();' % (name, self._refname),
835 1.1 christos ' if (msg->%s_data == NULL)' % name,
836 1.1 christos ' return (-1);',
837 1.1 christos ' msg->%s_set = 1;' % name,
838 1.1 christos ' }',
839 1.1 christos ' *value = msg->%s_data;' % name,
840 1.1 christos ' return (0);',
841 1.1 christos '}' ]
842 1.1 christos return code
843 1.1 christos
844 1.1 christos def CodeAssign(self):
845 1.1 christos name = self._name
846 1.1 christos code = """int
847 1.1 christos %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
848 1.1 christos const %(ctype)s value)
849 1.1 christos {
850 1.1 christos struct evbuffer *tmp = NULL;
851 1.1 christos if (msg->%(name)s_set) {
852 1.1 christos %(refname)s_clear(msg->%(name)s_data);
853 1.1 christos msg->%(name)s_set = 0;
854 1.1 christos } else {
855 1.1 christos msg->%(name)s_data = %(refname)s_new();
856 1.1 christos if (msg->%(name)s_data == NULL) {
857 1.1 christos event_warn("%%s: %(refname)s_new()", __func__);
858 1.1 christos goto error;
859 1.1 christos }
860 1.1 christos }
861 1.1 christos if ((tmp = evbuffer_new()) == NULL) {
862 1.1 christos event_warn("%%s: evbuffer_new()", __func__);
863 1.1 christos goto error;
864 1.1 christos }
865 1.1 christos %(refname)s_marshal(tmp, value);
866 1.1 christos if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) {
867 1.1 christos event_warnx("%%s: %(refname)s_unmarshal", __func__);
868 1.1 christos goto error;
869 1.1 christos }
870 1.1 christos msg->%(name)s_set = 1;
871 1.1 christos evbuffer_free(tmp);
872 1.1 christos return (0);
873 1.1 christos error:
874 1.1 christos if (tmp != NULL)
875 1.1 christos evbuffer_free(tmp);
876 1.1 christos if (msg->%(name)s_data != NULL) {
877 1.1 christos %(refname)s_free(msg->%(name)s_data);
878 1.1 christos msg->%(name)s_data = NULL;
879 1.1 christos }
880 1.1 christos return (-1);
881 1.1 christos }""" % self.GetTranslation()
882 1.1 christos return code.split('\n')
883 1.1 christos
884 1.1 christos def CodeComplete(self, structname, var_name):
885 1.1 christos code = [ 'if (%(structname)s->%(name)s_set && '
886 1.1 christos '%(refname)s_complete(%(var)s) == -1)',
887 1.1 christos ' return (-1);' ]
888 1.1 christos
889 1.1 christos return TranslateList(code, self.GetTranslation({
890 1.1 christos 'structname' : structname,
891 1.1 christos 'var' : var_name }))
892 1.1 christos
893 1.1 christos def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
894 1.1 christos code = ['%(var)s = %(refname)s_new();',
895 1.1 christos 'if (%(var)s == NULL)',
896 1.1 christos ' return (-1);',
897 1.1 christos 'if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag)s, '
898 1.1 christos '%(var)s) == -1) {',
899 1.1 christos ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
900 1.1 christos ' return (-1);',
901 1.1 christos '}'
902 1.1 christos ]
903 1.1 christos code = '\n'.join(code) % self.GetTranslation({
904 1.1 christos 'buf' : buf,
905 1.1 christos 'tag' : tag_name,
906 1.1 christos 'var' : var_name })
907 1.1 christos return code.split('\n')
908 1.1 christos
909 1.1 christos def CodeMarshal(self, buf, tag_name, var_name, var_len):
910 1.1 christos code = ['evtag_marshal_%s(%s, %s, %s);' % (
911 1.1 christos self._refname, buf, tag_name, var_name)]
912 1.1 christos return code
913 1.1 christos
914 1.1 christos def CodeClear(self, structname):
915 1.1 christos code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
916 1.1 christos ' %s_free(%s->%s_data);' % (
917 1.1 christos self._refname, structname, self.Name()),
918 1.1 christos ' %s->%s_data = NULL;' % (structname, self.Name()),
919 1.1 christos ' %s->%s_set = 0;' % (structname, self.Name()),
920 1.1 christos '}'
921 1.1 christos ]
922 1.1 christos
923 1.1 christos return code
924 1.1 christos
925 1.1 christos def CodeInitialize(self, name):
926 1.1 christos code = ['%s->%s_data = NULL;' % (name, self._name)]
927 1.1 christos return code
928 1.1 christos
929 1.1 christos def CodeFree(self, name):
930 1.1 christos code = ['if (%s->%s_data != NULL)' % (name, self._name),
931 1.1 christos ' %s_free(%s->%s_data);' % (
932 1.1 christos self._refname, name, self._name)]
933 1.1 christos
934 1.1 christos return code
935 1.1 christos
936 1.1 christos def Declaration(self):
937 1.1 christos dcl = ['%s %s_data;' % (self._ctype, self._name)]
938 1.1 christos
939 1.1 christos return dcl
940 1.1 christos
941 1.1 christos class EntryVarBytes(Entry):
942 1.1 christos def __init__(self, type, name, tag):
943 1.1 christos # Init base class
944 1.1 christos Entry.__init__(self, type, name, tag)
945 1.1 christos
946 1.1 christos self._ctype = 'ev_uint8_t *'
947 1.1 christos
948 1.1 christos def GetInitializer(self):
949 1.1 christos return "NULL"
950 1.1 christos
951 1.1 christos def GetVarLen(self, var):
952 1.1 christos return '%(var)s->%(name)s_length' % self.GetTranslation({ 'var' : var })
953 1.1 christos
954 1.1 christos def CodeArrayAdd(self, varname, value):
955 1.1 christos # xxx: copy
956 1.1 christos return [ '%(varname)s = NULL;' % { 'varname' : varname } ]
957 1.1 christos
958 1.1 christos def GetDeclaration(self, funcname):
959 1.1 christos code = [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % (
960 1.1 christos funcname, self._struct.Name(), self._ctype ) ]
961 1.1 christos return code
962 1.1 christos
963 1.1 christos def AssignDeclaration(self, funcname):
964 1.1 christos code = [ 'int %s(struct %s *, const %s, ev_uint32_t);' % (
965 1.1 christos funcname, self._struct.Name(), self._ctype ) ]
966 1.1 christos return code
967 1.1 christos
968 1.1 christos def CodeAssign(self):
969 1.1 christos name = self._name
970 1.1 christos code = [ 'int',
971 1.1 christos '%s_%s_assign(struct %s *msg, '
972 1.1 christos 'const %s value, ev_uint32_t len)' % (
973 1.1 christos self._struct.Name(), name,
974 1.1 christos self._struct.Name(), self._ctype),
975 1.1 christos '{',
976 1.1 christos ' if (msg->%s_data != NULL)' % name,
977 1.1 christos ' free (msg->%s_data);' % name,
978 1.1 christos ' msg->%s_data = malloc(len);' % name,
979 1.1 christos ' if (msg->%s_data == NULL)' % name,
980 1.1 christos ' return (-1);',
981 1.1 christos ' msg->%s_set = 1;' % name,
982 1.1 christos ' msg->%s_length = len;' % name,
983 1.1 christos ' memcpy(msg->%s_data, value, len);' % name,
984 1.1 christos ' return (0);',
985 1.1 christos '}' ]
986 1.1 christos return code
987 1.1 christos
988 1.1 christos def CodeGet(self):
989 1.1 christos name = self._name
990 1.1 christos code = [ 'int',
991 1.1 christos '%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)' % (
992 1.1 christos self._struct.Name(), name,
993 1.1 christos self._struct.Name(), self._ctype),
994 1.1 christos '{',
995 1.1 christos ' if (msg->%s_set != 1)' % name,
996 1.1 christos ' return (-1);',
997 1.1 christos ' *value = msg->%s_data;' % name,
998 1.1 christos ' *plen = msg->%s_length;' % name,
999 1.1 christos ' return (0);',
1000 1.1 christos '}' ]
1001 1.1 christos return code
1002 1.1 christos
1003 1.1 christos def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
1004 1.1 christos code = ['if (evtag_payload_length(%(buf)s, &%(varlen)s) == -1)',
1005 1.1 christos ' return (-1);',
1006 1.1 christos # We do not want DoS opportunities
1007 1.1 christos 'if (%(varlen)s > evbuffer_get_length(%(buf)s))',
1008 1.1 christos ' return (-1);',
1009 1.1 christos 'if ((%(var)s = malloc(%(varlen)s)) == NULL)',
1010 1.1 christos ' return (-1);',
1011 1.1 christos 'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, %(var)s, '
1012 1.1 christos '%(varlen)s) == -1) {',
1013 1.1 christos ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
1014 1.1 christos ' return (-1);',
1015 1.1 christos '}'
1016 1.1 christos ]
1017 1.1 christos code = '\n'.join(code) % self.GetTranslation({
1018 1.1 christos 'buf' : buf,
1019 1.1 christos 'tag' : tag_name,
1020 1.1 christos 'var' : var_name,
1021 1.1 christos 'varlen' : var_len })
1022 1.1 christos return code.split('\n')
1023 1.1 christos
1024 1.1 christos def CodeMarshal(self, buf, tag_name, var_name, var_len):
1025 1.1 christos code = ['evtag_marshal(%s, %s, %s, %s);' % (
1026 1.1 christos buf, tag_name, var_name, var_len)]
1027 1.1 christos return code
1028 1.1 christos
1029 1.1 christos def CodeClear(self, structname):
1030 1.1 christos code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
1031 1.1 christos ' free (%s->%s_data);' % (structname, self.Name()),
1032 1.1 christos ' %s->%s_data = NULL;' % (structname, self.Name()),
1033 1.1 christos ' %s->%s_length = 0;' % (structname, self.Name()),
1034 1.1 christos ' %s->%s_set = 0;' % (structname, self.Name()),
1035 1.1 christos '}'
1036 1.1 christos ]
1037 1.1 christos
1038 1.1 christos return code
1039 1.1 christos
1040 1.1 christos def CodeInitialize(self, name):
1041 1.1 christos code = ['%s->%s_data = NULL;' % (name, self._name),
1042 1.1 christos '%s->%s_length = 0;' % (name, self._name) ]
1043 1.1 christos return code
1044 1.1 christos
1045 1.1 christos def CodeFree(self, name):
1046 1.1 christos code = ['if (%s->%s_data != NULL)' % (name, self._name),
1047 1.1 christos ' free(%s->%s_data);' % (name, self._name)]
1048 1.1 christos
1049 1.1 christos return code
1050 1.1 christos
1051 1.1 christos def Declaration(self):
1052 1.1 christos dcl = ['ev_uint8_t *%s_data;' % self._name,
1053 1.1 christos 'ev_uint32_t %s_length;' % self._name]
1054 1.1 christos
1055 1.1 christos return dcl
1056 1.1 christos
1057 1.1 christos class EntryArray(Entry):
1058 1.1 christos def __init__(self, entry):
1059 1.1 christos # Init base class
1060 1.1 christos Entry.__init__(self, entry._type, entry._name, entry._tag)
1061 1.1 christos
1062 1.1 christos self._entry = entry
1063 1.1 christos self._refname = entry._refname
1064 1.1 christos self._ctype = self._entry._ctype
1065 1.1 christos self._optional = True
1066 1.1 christos self._optpointer = self._entry._optpointer
1067 1.1 christos self._optaddarg = self._entry._optaddarg
1068 1.1 christos
1069 1.1 christos # provide a new function for accessing the variable name
1070 1.1 christos def GetVarName(var_name):
1071 1.1 christos return '%(var)s->%(name)s_data[%(index)s]' % \
1072 1.1 christos self._entry.GetTranslation({'var' : var_name,
1073 1.1 christos 'index' : self._index})
1074 1.1 christos self._entry.GetVarName = GetVarName
1075 1.1 christos
1076 1.1 christos def GetInitializer(self):
1077 1.1 christos return "NULL"
1078 1.1 christos
1079 1.1 christos def GetVarName(self, var_name):
1080 1.1 christos return var_name
1081 1.1 christos
1082 1.1 christos def GetVarLen(self, var_name):
1083 1.1 christos return '-1'
1084 1.1 christos
1085 1.1 christos def GetDeclaration(self, funcname):
1086 1.1 christos """Allows direct access to elements of the array."""
1087 1.1 christos code = [
1088 1.1 christos 'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' %
1089 1.1 christos self.GetTranslation({ 'funcname' : funcname }) ]
1090 1.1 christos return code
1091 1.1 christos
1092 1.1 christos def AssignDeclaration(self, funcname):
1093 1.1 christos code = [ 'int %s(struct %s *, int, const %s);' % (
1094 1.1 christos funcname, self._struct.Name(), self._ctype ) ]
1095 1.1 christos return code
1096 1.1 christos
1097 1.1 christos def AddDeclaration(self, funcname):
1098 1.1 christos code = [
1099 1.1 christos '%(ctype)s %(optpointer)s '
1100 1.1 christos '%(funcname)s(struct %(parent_name)s *msg%(optaddarg)s);' % \
1101 1.1 christos self.GetTranslation({ 'funcname' : funcname }) ]
1102 1.1 christos return code
1103 1.1 christos
1104 1.1 christos def CodeGet(self):
1105 1.1 christos code = """int
1106 1.1 christos %(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset,
1107 1.1 christos %(ctype)s *value)
1108 1.1 christos {
1109 1.1 christos if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length)
1110 1.1 christos return (-1);
1111 1.1 christos *value = msg->%(name)s_data[offset];
1112 1.1 christos return (0);
1113 1.1 christos }""" % self.GetTranslation()
1114 1.1 christos
1115 1.1 christos return code.split('\n')
1116 1.1 christos
1117 1.1 christos def CodeAssign(self):
1118 1.1 christos code = [
1119 1.1 christos 'int',
1120 1.1 christos '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,',
1121 1.1 christos ' const %(ctype)s value)',
1122 1.1 christos '{',
1123 1.1 christos ' if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)',
1124 1.1 christos ' return (-1);\n',
1125 1.1 christos ' {' ]
1126 1.1 christos code = TranslateList(code, self.GetTranslation())
1127 1.1 christos
1128 1.1 christos codearrayassign = self._entry.CodeArrayAssign(
1129 1.1 christos 'msg->%(name)s_data[off]' % self.GetTranslation(), 'value')
1130 1.1 christos code += map(lambda x: ' ' + x, codearrayassign)
1131 1.1 christos
1132 1.1 christos code += TranslateList([
1133 1.1 christos ' }',
1134 1.1 christos ' return (0);',
1135 1.1 christos '}' ], self.GetTranslation())
1136 1.1 christos
1137 1.1 christos return code
1138 1.1 christos
1139 1.1 christos def CodeAdd(self):
1140 1.1 christos codearrayadd = self._entry.CodeArrayAdd(
1141 1.1 christos 'msg->%(name)s_data[msg->%(name)s_length - 1]' % self.GetTranslation(),
1142 1.1 christos 'value')
1143 1.1 christos code = [
1144 1.1 christos 'static int',
1145 1.1 christos '%(parent_name)s_%(name)s_expand_to_hold_more('
1146 1.1 christos 'struct %(parent_name)s *msg)',
1147 1.1 christos '{',
1148 1.1 christos ' int tobe_allocated = msg->%(name)s_num_allocated;',
1149 1.1 christos ' %(ctype)s* new_data = NULL;',
1150 1.1 christos ' tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;',
1151 1.1 christos ' new_data = (%(ctype)s*) realloc(msg->%(name)s_data,',
1152 1.1 christos ' tobe_allocated * sizeof(%(ctype)s));',
1153 1.1 christos ' if (new_data == NULL)',
1154 1.1 christos ' return -1;',
1155 1.1 christos ' msg->%(name)s_data = new_data;',
1156 1.1 christos ' msg->%(name)s_num_allocated = tobe_allocated;',
1157 1.1 christos ' return 0;'
1158 1.1 christos '}',
1159 1.1 christos '',
1160 1.1 christos '%(ctype)s %(optpointer)s',
1161 1.1 christos '%(parent_name)s_%(name)s_add('
1162 1.1 christos 'struct %(parent_name)s *msg%(optaddarg)s)',
1163 1.1 christos '{',
1164 1.1 christos ' if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {',
1165 1.1 christos ' if (%(parent_name)s_%(name)s_expand_to_hold_more(msg)<0)',
1166 1.1 christos ' goto error;',
1167 1.1 christos ' }' ]
1168 1.1 christos
1169 1.1 christos code = TranslateList(code, self.GetTranslation())
1170 1.1 christos
1171 1.1 christos code += map(lambda x: ' ' + x, codearrayadd)
1172 1.1 christos
1173 1.1 christos code += TranslateList([
1174 1.1 christos ' msg->%(name)s_set = 1;',
1175 1.1 christos ' return %(optreference)s(msg->%(name)s_data['
1176 1.1 christos 'msg->%(name)s_length - 1]);',
1177 1.1 christos 'error:',
1178 1.1 christos ' --msg->%(name)s_length;',
1179 1.1 christos ' return (NULL);',
1180 1.1 christos '}' ], self.GetTranslation())
1181 1.1 christos
1182 1.1 christos return code
1183 1.1 christos
1184 1.1 christos def CodeComplete(self, structname, var_name):
1185 1.1 christos self._index = 'i'
1186 1.1 christos tmp = self._entry.CodeComplete(structname, self._entry.GetVarName(var_name))
1187 1.1 christos # skip the whole loop if there is nothing to check
1188 1.1 christos if not tmp:
1189 1.1 christos return []
1190 1.1 christos
1191 1.1 christos translate = self.GetTranslation({ 'structname' : structname })
1192 1.1 christos code = [
1193 1.1 christos '{',
1194 1.1 christos ' int i;',
1195 1.1 christos ' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ]
1196 1.1 christos
1197 1.1 christos code = TranslateList(code, translate)
1198 1.1 christos
1199 1.1 christos code += map(lambda x: ' ' + x, tmp)
1200 1.1 christos
1201 1.1 christos code += [
1202 1.1 christos ' }',
1203 1.1 christos '}' ]
1204 1.1 christos
1205 1.1 christos return code
1206 1.1 christos
1207 1.1 christos def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
1208 1.1 christos translate = self.GetTranslation({ 'var' : var_name,
1209 1.1 christos 'buf' : buf,
1210 1.1 christos 'tag' : tag_name,
1211 1.1 christos 'init' : self._entry.GetInitializer()})
1212 1.1 christos code = [
1213 1.1 christos 'if (%(var)s->%(name)s_length >= %(var)s->%(name)s_num_allocated &&',
1214 1.1 christos ' %(parent_name)s_%(name)s_expand_to_hold_more(%(var)s) < 0) {',
1215 1.1 christos ' puts("HEY NOW");',
1216 1.1 christos ' return (-1);',
1217 1.1 christos '}']
1218 1.1 christos
1219 1.1 christos # the unmarshal code directly returns
1220 1.1 christos code = TranslateList(code, translate)
1221 1.1 christos
1222 1.1 christos self._index = '%(var)s->%(name)s_length' % translate
1223 1.1 christos code += self._entry.CodeUnmarshal(buf, tag_name,
1224 1.1 christos self._entry.GetVarName(var_name),
1225 1.1 christos self._entry.GetVarLen(var_name))
1226 1.1 christos
1227 1.1 christos code += [ '++%(var)s->%(name)s_length;' % translate ]
1228 1.1 christos
1229 1.1 christos return code
1230 1.1 christos
1231 1.1 christos def CodeMarshal(self, buf, tag_name, var_name, var_len):
1232 1.1 christos code = ['{',
1233 1.1 christos ' int i;',
1234 1.1 christos ' for (i = 0; i < %(var)s->%(name)s_length; ++i) {' ]
1235 1.1 christos
1236 1.1 christos self._index = 'i'
1237 1.1 christos code += self._entry.CodeMarshal(buf, tag_name,
1238 1.1 christos self._entry.GetVarName(var_name),
1239 1.1 christos self._entry.GetVarLen(var_name))
1240 1.1 christos code += [' }',
1241 1.1 christos '}'
1242 1.1 christos ]
1243 1.1 christos
1244 1.1 christos code = "\n".join(code) % self.GetTranslation({ 'var' : var_name })
1245 1.1 christos
1246 1.1 christos return code.split('\n')
1247 1.1 christos
1248 1.1 christos def CodeClear(self, structname):
1249 1.1 christos translate = self.GetTranslation({ 'structname' : structname })
1250 1.1 christos codearrayfree = self._entry.CodeArrayFree(
1251 1.1 christos '%(structname)s->%(name)s_data[i]' % self.GetTranslation(
1252 1.1 christos { 'structname' : structname } ))
1253 1.1 christos
1254 1.1 christos code = [ 'if (%(structname)s->%(name)s_set == 1) {' ]
1255 1.1 christos
1256 1.1 christos if codearrayfree:
1257 1.1 christos code += [
1258 1.1 christos ' int i;',
1259 1.1 christos ' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ]
1260 1.1 christos
1261 1.1 christos code = TranslateList(code, translate)
1262 1.1 christos
1263 1.1 christos if codearrayfree:
1264 1.1 christos code += map(lambda x: ' ' + x, codearrayfree)
1265 1.1 christos code += [
1266 1.1 christos ' }' ]
1267 1.1 christos
1268 1.1 christos code += TranslateList([
1269 1.1 christos ' free(%(structname)s->%(name)s_data);',
1270 1.1 christos ' %(structname)s->%(name)s_data = NULL;',
1271 1.1 christos ' %(structname)s->%(name)s_set = 0;',
1272 1.1 christos ' %(structname)s->%(name)s_length = 0;',
1273 1.1 christos ' %(structname)s->%(name)s_num_allocated = 0;',
1274 1.1 christos '}'
1275 1.1 christos ], translate)
1276 1.1 christos
1277 1.1 christos return code
1278 1.1 christos
1279 1.1 christos def CodeInitialize(self, name):
1280 1.1 christos code = ['%s->%s_data = NULL;' % (name, self._name),
1281 1.1 christos '%s->%s_length = 0;' % (name, self._name),
1282 1.1 christos '%s->%s_num_allocated = 0;' % (name, self._name)]
1283 1.1 christos return code
1284 1.1 christos
1285 1.1 christos def CodeFree(self, structname):
1286 1.1 christos code = self.CodeClear(structname);
1287 1.1 christos
1288 1.1 christos code += TranslateList([
1289 1.1 christos 'free(%(structname)s->%(name)s_data);' ],
1290 1.1 christos self.GetTranslation({'structname' : structname }))
1291 1.1 christos
1292 1.1 christos return code
1293 1.1 christos
1294 1.1 christos def Declaration(self):
1295 1.1 christos dcl = ['%s *%s_data;' % (self._ctype, self._name),
1296 1.1 christos 'int %s_length;' % self._name,
1297 1.1 christos 'int %s_num_allocated;' % self._name ]
1298 1.1 christos
1299 1.1 christos return dcl
1300 1.1 christos
1301 1.1 christos def NormalizeLine(line):
1302 1.1 christos global white
1303 1.1 christos global cppcomment
1304 1.1 christos
1305 1.1 christos line = cppcomment.sub('', line)
1306 1.1 christos line = line.strip()
1307 1.1 christos line = white.sub(' ', line)
1308 1.1 christos
1309 1.1 christos return line
1310 1.1 christos
1311 1.1 christos def ProcessOneEntry(factory, newstruct, entry):
1312 1.1 christos optional = 0
1313 1.1 christos array = 0
1314 1.1 christos entry_type = ''
1315 1.1 christos name = ''
1316 1.1 christos tag = ''
1317 1.1 christos tag_set = None
1318 1.1 christos separator = ''
1319 1.1 christos fixed_length = ''
1320 1.1 christos
1321 1.1 christos tokens = entry.split(' ')
1322 1.1 christos while tokens:
1323 1.1 christos token = tokens[0]
1324 1.1 christos tokens = tokens[1:]
1325 1.1 christos
1326 1.1 christos if not entry_type:
1327 1.1 christos if not optional and token == 'optional':
1328 1.1 christos optional = 1
1329 1.1 christos continue
1330 1.1 christos
1331 1.1 christos if not array and token == 'array':
1332 1.1 christos array = 1
1333 1.1 christos continue
1334 1.1 christos
1335 1.1 christos if not entry_type:
1336 1.1 christos entry_type = token
1337 1.1 christos continue
1338 1.1 christos
1339 1.1 christos if not name:
1340 1.1 christos res = re.match(r'^([^\[\]]+)(\[.*\])?$', token)
1341 1.1 christos if not res:
1342 1.1 christos raise RpcGenError(
1343 1.1 christos 'Cannot parse name: \"%s\" '
1344 1.1 christos 'around line %d' % (entry, line_count))
1345 1.1 christos name = res.group(1)
1346 1.1 christos fixed_length = res.group(2)
1347 1.1 christos if fixed_length:
1348 1.1 christos fixed_length = fixed_length[1:-1]
1349 1.1 christos continue
1350 1.1 christos
1351 1.1 christos if not separator:
1352 1.1 christos separator = token
1353 1.1 christos if separator != '=':
1354 1.1 christos raise RpcGenError('Expected "=" after name \"%s\" got %s'
1355 1.1 christos % (name, token))
1356 1.1 christos continue
1357 1.1 christos
1358 1.1 christos if not tag_set:
1359 1.1 christos tag_set = 1
1360 1.1 christos if not re.match(r'^(0x)?[0-9]+$', token):
1361 1.1 christos raise RpcGenError('Expected tag number: \"%s\"' % entry)
1362 1.1 christos tag = int(token, 0)
1363 1.1 christos continue
1364 1.1 christos
1365 1.1 christos raise RpcGenError('Cannot parse \"%s\"' % entry)
1366 1.1 christos
1367 1.1 christos if not tag_set:
1368 1.1 christos raise RpcGenError('Need tag number: \"%s\"' % entry)
1369 1.1 christos
1370 1.1 christos # Create the right entry
1371 1.1 christos if entry_type == 'bytes':
1372 1.1 christos if fixed_length:
1373 1.1 christos newentry = factory.EntryBytes(entry_type, name, tag, fixed_length)
1374 1.1 christos else:
1375 1.1 christos newentry = factory.EntryVarBytes(entry_type, name, tag)
1376 1.1 christos elif entry_type == 'int' and not fixed_length:
1377 1.1 christos newentry = factory.EntryInt(entry_type, name, tag)
1378 1.1 christos elif entry_type == 'int64' and not fixed_length:
1379 1.1 christos newentry = factory.EntryInt(entry_type, name, tag, bits=64)
1380 1.1 christos elif entry_type == 'string' and not fixed_length:
1381 1.1 christos newentry = factory.EntryString(entry_type, name, tag)
1382 1.1 christos else:
1383 1.1 christos res = structref.match(entry_type)
1384 1.1 christos if res:
1385 1.1 christos # References another struct defined in our file
1386 1.1 christos newentry = factory.EntryStruct(entry_type, name, tag, res.group(1))
1387 1.1 christos else:
1388 1.1 christos raise RpcGenError('Bad type: "%s" in "%s"' % (entry_type, entry))
1389 1.1 christos
1390 1.1 christos structs = []
1391 1.1 christos
1392 1.1 christos if optional:
1393 1.1 christos newentry.MakeOptional()
1394 1.1 christos if array:
1395 1.1 christos newentry.MakeArray()
1396 1.1 christos
1397 1.1 christos newentry.SetStruct(newstruct)
1398 1.1 christos newentry.SetLineCount(line_count)
1399 1.1 christos newentry.Verify()
1400 1.1 christos
1401 1.1 christos if array:
1402 1.1 christos # We need to encapsulate this entry into a struct
1403 1.1 christos newname = newentry.Name()+ '_array'
1404 1.1 christos
1405 1.1 christos # Now borgify the new entry.
1406 1.1 christos newentry = factory.EntryArray(newentry)
1407 1.1 christos newentry.SetStruct(newstruct)
1408 1.1 christos newentry.SetLineCount(line_count)
1409 1.1 christos newentry.MakeArray()
1410 1.1 christos
1411 1.1 christos newstruct.AddEntry(newentry)
1412 1.1 christos
1413 1.1 christos return structs
1414 1.1 christos
1415 1.1 christos def ProcessStruct(factory, data):
1416 1.1 christos tokens = data.split(' ')
1417 1.1 christos
1418 1.1 christos # First three tokens are: 'struct' 'name' '{'
1419 1.1 christos newstruct = factory.Struct(tokens[1])
1420 1.1 christos
1421 1.1 christos inside = ' '.join(tokens[3:-1])
1422 1.1 christos
1423 1.1 christos tokens = inside.split(';')
1424 1.1 christos
1425 1.1 christos structs = []
1426 1.1 christos
1427 1.1 christos for entry in tokens:
1428 1.1 christos entry = NormalizeLine(entry)
1429 1.1 christos if not entry:
1430 1.1 christos continue
1431 1.1 christos
1432 1.1 christos # It's possible that new structs get defined in here
1433 1.1 christos structs.extend(ProcessOneEntry(factory, newstruct, entry))
1434 1.1 christos
1435 1.1 christos structs.append(newstruct)
1436 1.1 christos return structs
1437 1.1 christos
1438 1.1 christos def GetNextStruct(file):
1439 1.1 christos global line_count
1440 1.1 christos global cppdirect
1441 1.1 christos
1442 1.1 christos got_struct = 0
1443 1.1 christos
1444 1.1 christos processed_lines = []
1445 1.1 christos
1446 1.1 christos have_c_comment = 0
1447 1.1 christos data = ''
1448 1.1 christos while 1:
1449 1.1 christos line = file.readline()
1450 1.1 christos if not line:
1451 1.1 christos break
1452 1.1 christos
1453 1.1 christos line_count += 1
1454 1.1 christos line = line[:-1]
1455 1.1 christos
1456 1.1 christos if not have_c_comment and re.search(r'/\*', line):
1457 1.1 christos if re.search(r'/\*.*?\*/', line):
1458 1.1 christos line = re.sub(r'/\*.*?\*/', '', line)
1459 1.1 christos else:
1460 1.1 christos line = re.sub(r'/\*.*$', '', line)
1461 1.1 christos have_c_comment = 1
1462 1.1 christos
1463 1.1 christos if have_c_comment:
1464 1.1 christos if not re.search(r'\*/', line):
1465 1.1 christos continue
1466 1.1 christos have_c_comment = 0
1467 1.1 christos line = re.sub(r'^.*\*/', '', line)
1468 1.1 christos
1469 1.1 christos line = NormalizeLine(line)
1470 1.1 christos
1471 1.1 christos if not line:
1472 1.1 christos continue
1473 1.1 christos
1474 1.1 christos if not got_struct:
1475 1.1 christos if re.match(r'#include ["<].*[>"]', line):
1476 1.1 christos cppdirect.append(line)
1477 1.1 christos continue
1478 1.1 christos
1479 1.1 christos if re.match(r'^#(if( |def)|endif)', line):
1480 1.1 christos cppdirect.append(line)
1481 1.1 christos continue
1482 1.1 christos
1483 1.1 christos if re.match(r'^#define', line):
1484 1.1 christos headerdirect.append(line)
1485 1.1 christos continue
1486 1.1 christos
1487 1.1 christos if not structdef.match(line):
1488 1.1 christos raise RpcGenError('Missing struct on line %d: %s'
1489 1.1 christos % (line_count, line))
1490 1.1 christos else:
1491 1.1 christos got_struct = 1
1492 1.1 christos data += line
1493 1.1 christos continue
1494 1.1 christos
1495 1.1 christos # We are inside the struct
1496 1.1 christos tokens = line.split('}')
1497 1.1 christos if len(tokens) == 1:
1498 1.1 christos data += ' ' + line
1499 1.1 christos continue
1500 1.1 christos
1501 1.1 christos if len(tokens[1]):
1502 1.1 christos raise RpcGenError('Trailing garbage after struct on line %d'
1503 1.1 christos % line_count)
1504 1.1 christos
1505 1.1 christos # We found the end of the struct
1506 1.1 christos data += ' %s}' % tokens[0]
1507 1.1 christos break
1508 1.1 christos
1509 1.1 christos # Remove any comments, that might be in there
1510 1.1 christos data = re.sub(r'/\*.*\*/', '', data)
1511 1.1 christos
1512 1.1 christos return data
1513 1.1 christos
1514 1.1 christos
1515 1.1 christos def Parse(factory, file):
1516 1.1 christos """
1517 1.1 christos Parses the input file and returns C code and corresponding header file.
1518 1.1 christos """
1519 1.1 christos
1520 1.1 christos entities = []
1521 1.1 christos
1522 1.1 christos while 1:
1523 1.1 christos # Just gets the whole struct nicely formatted
1524 1.1 christos data = GetNextStruct(file)
1525 1.1 christos
1526 1.1 christos if not data:
1527 1.1 christos break
1528 1.1 christos
1529 1.1 christos entities.extend(ProcessStruct(factory, data))
1530 1.1 christos
1531 1.1 christos return entities
1532 1.1 christos
1533 1.1 christos class CCodeGenerator:
1534 1.1 christos def __init__(self):
1535 1.1 christos pass
1536 1.1 christos
1537 1.1 christos def GuardName(self, name):
1538 1.1 christos # Use the complete provided path to the input file, with all
1539 1.1 christos # non-identifier characters replaced with underscores, to
1540 1.1 christos # reduce the chance of a collision between guard macros.
1541 1.1 christos return 'EVENT_RPCOUT_' + nonident.sub('_', name).upper() + '_'
1542 1.1 christos
1543 1.1 christos def HeaderPreamble(self, name):
1544 1.1 christos guard = self.GuardName(name)
1545 1.1 christos pre = (
1546 1.1 christos '/*\n'
1547 1.1 christos ' * Automatically generated from %s\n'
1548 1.1 christos ' */\n\n'
1549 1.1 christos '#ifndef %s\n'
1550 1.1 christos '#define %s\n\n' ) % (
1551 1.1 christos name, guard, guard)
1552 1.1 christos
1553 1.1 christos for statement in headerdirect:
1554 1.1 christos pre += '%s\n' % statement
1555 1.1 christos if headerdirect:
1556 1.1 christos pre += '\n'
1557 1.1 christos
1558 1.1 christos pre += (
1559 1.1 christos '#include <event2/util.h> /* for ev_uint*_t */\n'
1560 1.1 christos '#include <event2/rpc.h>\n'
1561 1.1 christos )
1562 1.1 christos
1563 1.1 christos return pre
1564 1.1 christos
1565 1.1 christos def HeaderPostamble(self, name):
1566 1.1 christos guard = self.GuardName(name)
1567 1.1 christos return '#endif /* %s */' % guard
1568 1.1 christos
1569 1.1 christos def BodyPreamble(self, name, header_file):
1570 1.1 christos global _NAME
1571 1.1 christos global _VERSION
1572 1.1 christos
1573 1.1 christos slash = header_file.rfind('/')
1574 1.1 christos if slash != -1:
1575 1.1 christos header_file = header_file[slash+1:]
1576 1.1 christos
1577 1.1 christos pre = ( '/*\n'
1578 1.1 christos ' * Automatically generated from %s\n'
1579 1.1 christos ' * by %s/%s. DO NOT EDIT THIS FILE.\n'
1580 1.1 christos ' */\n\n' ) % (name, _NAME, _VERSION)
1581 1.1 christos pre += ( '#include <stdlib.h>\n'
1582 1.1 christos '#include <string.h>\n'
1583 1.1 christos '#include <assert.h>\n'
1584 1.1 christos '#include <event2/event-config.h>\n'
1585 1.1 christos '#include <event2/event.h>\n'
1586 1.1 christos '#include <event2/buffer.h>\n'
1587 1.1 christos '#include <event2/tag.h>\n\n'
1588 1.1 christos '#ifdef EVENT____func__\n'
1589 1.1 christos '#define __func__ EVENT____func__\n'
1590 1.1 christos '#endif\n\n'
1591 1.1 christos )
1592 1.1 christos
1593 1.1 christos for statement in cppdirect:
1594 1.1 christos pre += '%s\n' % statement
1595 1.1 christos
1596 1.1 christos pre += '\n#include "%s"\n\n' % header_file
1597 1.1 christos
1598 1.1 christos pre += 'void event_warn(const char *fmt, ...);\n'
1599 1.1 christos pre += 'void event_warnx(const char *fmt, ...);\n\n'
1600 1.1 christos
1601 1.1 christos return pre
1602 1.1 christos
1603 1.1 christos def HeaderFilename(self, filename):
1604 1.1 christos return '.'.join(filename.split('.')[:-1]) + '.h'
1605 1.1 christos
1606 1.1 christos def CodeFilename(self, filename):
1607 1.1 christos return '.'.join(filename.split('.')[:-1]) + '.gen.c'
1608 1.1 christos
1609 1.1 christos def Struct(self, name):
1610 1.1 christos return StructCCode(name)
1611 1.1 christos
1612 1.1 christos def EntryBytes(self, entry_type, name, tag, fixed_length):
1613 1.1 christos return EntryBytes(entry_type, name, tag, fixed_length)
1614 1.1 christos
1615 1.1 christos def EntryVarBytes(self, entry_type, name, tag):
1616 1.1 christos return EntryVarBytes(entry_type, name, tag)
1617 1.1 christos
1618 1.1 christos def EntryInt(self, entry_type, name, tag, bits=32):
1619 1.1 christos return EntryInt(entry_type, name, tag, bits)
1620 1.1 christos
1621 1.1 christos def EntryString(self, entry_type, name, tag):
1622 1.1 christos return EntryString(entry_type, name, tag)
1623 1.1 christos
1624 1.1 christos def EntryStruct(self, entry_type, name, tag, struct_name):
1625 1.1 christos return EntryStruct(entry_type, name, tag, struct_name)
1626 1.1 christos
1627 1.1 christos def EntryArray(self, entry):
1628 1.1 christos return EntryArray(entry)
1629 1.1 christos
1630 1.1 christos class Usage(RpcGenError):
1631 1.1 christos def __init__(self, argv0):
1632 1.1 christos RpcGenError.__init__("usage: %s input.rpc [[output.h] output.c]"
1633 1.1 christos % argv0)
1634 1.1 christos
1635 1.1 christos class CommandLine:
1636 1.1 christos def __init__(self, argv):
1637 1.1 christos """Initialize a command-line to launch event_rpcgen, as if
1638 1.1 christos from a command-line with CommandLine(sys.argv). If you're
1639 1.1 christos calling this directly, remember to provide a dummy value
1640 1.1 christos for sys.argv[0]
1641 1.1 christos """
1642 1.1 christos self.filename = None
1643 1.1 christos self.header_file = None
1644 1.1 christos self.impl_file = None
1645 1.1 christos self.factory = CCodeGenerator()
1646 1.1 christos
1647 1.1 christos if len(argv) >= 2 and argv[1] == '--quiet':
1648 1.1 christos global QUIETLY
1649 1.1 christos QUIETLY = 1
1650 1.1 christos del argv[1]
1651 1.1 christos
1652 1.1 christos if len(argv) < 2 or len(argv) > 4:
1653 1.1 christos raise Usage(argv[0])
1654 1.1 christos
1655 1.1 christos self.filename = argv[1].replace('\\', '/')
1656 1.1 christos if len(argv) == 3:
1657 1.1 christos self.impl_file = argv[2].replace('\\', '/')
1658 1.1 christos if len(argv) == 4:
1659 1.1 christos self.header_file = argv[2].replace('\\', '/')
1660 1.1 christos self.impl_file = argv[3].replace('\\', '/')
1661 1.1 christos
1662 1.1 christos if not self.filename:
1663 1.1 christos raise Usage(argv[0])
1664 1.1 christos
1665 1.1 christos if not self.impl_file:
1666 1.1 christos self.impl_file = self.factory.CodeFilename(self.filename)
1667 1.1 christos
1668 1.1 christos if not self.header_file:
1669 1.1 christos self.header_file = self.factory.HeaderFilename(self.impl_file)
1670 1.1 christos
1671 1.1 christos if not self.impl_file.endswith('.c'):
1672 1.1 christos raise RpcGenError("can only generate C implementation files")
1673 1.1 christos if not self.header_file.endswith('.h'):
1674 1.1 christos raise RpcGenError("can only generate C header files")
1675 1.1 christos
1676 1.1 christos def run(self):
1677 1.1 christos filename = self.filename
1678 1.1 christos header_file = self.header_file
1679 1.1 christos impl_file = self.impl_file
1680 1.1 christos factory = self.factory
1681 1.1 christos
1682 1.1 christos declare('Reading \"%s\"' % filename)
1683 1.1 christos
1684 1.1 christos fp = open(filename, 'r')
1685 1.1 christos entities = Parse(factory, fp)
1686 1.1 christos fp.close()
1687 1.1 christos
1688 1.1 christos declare('... creating "%s"' % header_file)
1689 1.1 christos header_fp = open(header_file, 'w')
1690 1.1 christos print >>header_fp, factory.HeaderPreamble(filename)
1691 1.1 christos
1692 1.1 christos # Create forward declarations: allows other structs to reference
1693 1.1 christos # each other
1694 1.1 christos for entry in entities:
1695 1.1 christos entry.PrintForwardDeclaration(header_fp)
1696 1.1 christos print >>header_fp, ''
1697 1.1 christos
1698 1.1 christos for entry in entities:
1699 1.1 christos entry.PrintTags(header_fp)
1700 1.1 christos entry.PrintDeclaration(header_fp)
1701 1.1 christos print >>header_fp, factory.HeaderPostamble(filename)
1702 1.1 christos header_fp.close()
1703 1.1 christos
1704 1.1 christos declare('... creating "%s"' % impl_file)
1705 1.1 christos impl_fp = open(impl_file, 'w')
1706 1.1 christos print >>impl_fp, factory.BodyPreamble(filename, header_file)
1707 1.1 christos for entry in entities:
1708 1.1 christos entry.PrintCode(impl_fp)
1709 1.1 christos impl_fp.close()
1710 1.1 christos
1711 1.1 christos if __name__ == '__main__':
1712 1.1 christos try:
1713 1.1 christos CommandLine(sys.argv).run()
1714 1.1 christos sys.exit(0)
1715 1.1 christos
1716 1.1 christos except RpcGenError, e:
1717 1.1 christos print >>sys.stderr, e
1718 1.1 christos sys.exit(1)
1719 1.1 christos
1720 1.1 christos except EnvironmentError, e:
1721 1.1 christos if e.filename and e.strerror:
1722 1.1 christos print >>sys.stderr, "%s: %s" % (e.filename, e.strerror)
1723 1.1 christos sys.exit(1)
1724 1.1 christos elif e.strerror:
1725 1.1 christos print >> sys.stderr, e.strerror
1726 1.1 christos sys.exit(1)
1727 1.1 christos else:
1728 1.1 christos raise
1729