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