3 # Copyright (c) 2005 Niels Provos <provos@citi.umich.edu>
6 # Generates marshaling code based on libevent.
12 _NAME
= "event_rpcgen.py"
14 _STRUCT_RE
= '[a-z][a-z_0-9]*'
19 white
= re
.compile(r
'^\s+')
20 cppcomment
= re
.compile(r
'\/\/.*$')
24 # Holds everything that makes a struct
26 def __init__(self
, name
):
30 print >>sys
.stderr
, ' Created struct: %s' % name
32 def AddEntry(self
, entry
):
33 if self
._tags
.has_key(entry
.Tag()):
34 print >>sys
.stderr
, ( 'Entry "%s" duplicates tag number '
35 '%d from "%s" around line %d' ) % (
36 entry
.Name(), entry
.Tag(),
37 self
._tags
[entry
.Tag()], line_count
)
39 self
._entries
.append(entry
)
40 self
._tags
[entry
.Tag()] = entry
.Name()
41 print >>sys
.stderr
, ' Added entry: %s' % entry
.Name()
46 def EntryTagName(self
, entry
):
47 """Creates the name inside an enumeration for distinguishing data
49 name
= "%s_%s" % (self
._name
, entry
.Name())
52 def PrintIdented(self
, file, ident
, code
):
53 """Takes an array, add indentation to each entry and prints it."""
55 print >>file, '%s%s' % (ident
, entry
)
57 def PrintTags(self
, file):
58 """Prints the tag definitions for a structure."""
59 print >>file, '/* Tag definition for %s */' % self
._name
60 print >>file, 'enum %s_ {' % self
._name
.lower()
61 for entry
in self
._entries
:
62 print >>file, ' %s=%d,' % (self
.EntryTagName(entry
),
64 print >>file, ' %s_MAX_TAGS' % (self
._name
.upper())
67 def PrintForwardDeclaration(self
, file):
68 print >>file, 'struct %s;' % self
._name
70 def PrintDeclaration(self
, file):
71 print >>file, '/* Structure declaration for %s */' % self
._name
72 print >>file, 'struct %s_access_ {' % self
._name
73 for entry
in self
._entries
:
74 dcl
= entry
.AssignDeclaration('(*%s_assign)' % entry
.Name())
76 entry
.GetDeclaration('(*%s_get)' % entry
.Name()))
79 entry
.AddDeclaration('(*%s_add)' % entry
.Name()))
80 self
.PrintIdented(file, ' ', dcl
)
83 print >>file, 'struct %s {' % self
._name
84 print >>file, ' struct %s_access_ *base;\n' % self
._name
85 for entry
in self
._entries
:
86 dcl
= entry
.Declaration()
87 self
.PrintIdented(file, ' ', dcl
)
89 for entry
in self
._entries
:
90 print >>file, ' ev_uint8_t %s_set;' % entry
.Name()
94 """struct %(name)s *%(name)s_new(void);
95 void %(name)s_free(struct %(name)s *);
96 void %(name)s_clear(struct %(name)s *);
97 void %(name)s_marshal(struct evbuffer *, const struct %(name)s *);
98 int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *);
99 int %(name)s_complete(struct %(name)s *);
100 void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t,
101 const struct %(name)s *);
102 int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
103 struct %(name)s *);""" % { 'name' : self
._name
}
106 # Write a setting function of every variable
107 for entry
in self
._entries
:
108 self
.PrintIdented(file, '', entry
.AssignDeclaration(
109 entry
.AssignFuncName()))
110 self
.PrintIdented(file, '', entry
.GetDeclaration(
111 entry
.GetFuncName()))
113 self
.PrintIdented(file, '', entry
.AddDeclaration(
114 entry
.AddFuncName()))
116 print >>file, '/* --- %s done --- */\n' % self
._name
118 def PrintCode(self
, file):
119 print >>file, ('/*\n'
120 ' * Implementation of %s\n'
121 ' */\n') % self
._name
124 'static struct %(name)s_access_ __%(name)s_base = {' % \
125 { 'name' : self
._name
}
126 for entry
in self
._entries
:
127 self
.PrintIdented(file, ' ', entry
.CodeBase())
132 'struct %(name)s *\n'
133 '%(name)s_new(void)\n'
135 ' struct %(name)s *tmp;\n'
136 ' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n'
137 ' event_warn("%%s: malloc", __func__);\n'
140 ' tmp->base = &__%(name)s_base;\n') % { 'name' : self
._name
}
142 for entry
in self
._entries
:
143 self
.PrintIdented(file, ' ', entry
.CodeNew('tmp'))
144 print >>file, ' tmp->%s_set = 0;\n' % entry
.Name()
151 for entry
in self
._entries
:
153 self
.PrintIdented(file, '', entry
.CodeAdd())
157 for entry
in self
._entries
:
158 self
.PrintIdented(file, '', entry
.CodeAssign())
162 for entry
in self
._entries
:
163 self
.PrintIdented(file, '', entry
.CodeGet())
167 print >>file, ( 'void\n'
168 '%(name)s_clear(struct %(name)s *tmp)\n'
170 ) % { 'name' : self
._name
}
171 for entry
in self
._entries
:
172 self
.PrintIdented(file, ' ', entry
.CodeClear('tmp'))
177 print >>file, ( 'void\n'
178 '%(name)s_free(struct %(name)s *tmp)\n'
180 ) % { 'name' : self
._name
}
182 for entry
in self
._entries
:
183 self
.PrintIdented(file, ' ', entry
.CodeFree('tmp'))
185 print >>file, (' free(tmp);\n'
189 print >>file, ('void\n'
190 '%(name)s_marshal(struct evbuffer *evbuf, '
191 'const struct %(name)s *tmp)'
192 '{') % { 'name' : self
._name
}
193 for entry
in self
._entries
:
195 # Optional entries do not have to be set
198 print >>file, ' if (tmp->%s_set) {' % entry
.Name()
201 entry
.CodeMarshal('evbuf', self
.EntryTagName(entry
), 'tmp'))
208 print >>file, ('int\n'
209 '%(name)s_unmarshal(struct %(name)s *tmp, '
210 ' struct evbuffer *evbuf)\n'
212 ' ev_uint32_t tag;\n'
213 ' while (EVBUFFER_LENGTH(evbuf) > 0) {\n'
214 ' if (evtag_peek(evbuf, &tag) == -1)\n'
217 ) % { 'name' : self
._name
}
218 for entry
in self
._entries
:
219 print >>file, ' case %s:\n' % self
.EntryTagName(entry
)
220 if not entry
.Array():
222 ' if (tmp->%s_set)\n'
228 entry
.CodeUnmarshal('evbuf',
229 self
.EntryTagName(entry
), 'tmp'))
231 print >>file, ( ' tmp->%s_set = 1;\n' % entry
.Name() +
233 print >>file, ( ' default:\n'
237 # Check if it was decoded completely
238 print >>file, ( ' if (%(name)s_complete(tmp) == -1)\n'
240 ) % { 'name' : self
._name
}
242 # Successfully decoded
243 print >>file, ( ' return (0);\n'
246 # Checking if a structure has all the required data
249 '%(name)s_complete(struct %(name)s *msg)\n'
250 '{' ) % { 'name' : self
._name
}
251 for entry
in self
._entries
:
254 entry
.CodeComplete('msg'))
259 # Complete message unmarshaling
262 'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, '
263 'ev_uint32_t need_tag, struct %(name)s *msg)\n'
265 ' ev_uint32_t tag;\n'
268 ' struct evbuffer *tmp = evbuffer_new();\n'
270 ' if (evtag_unmarshal(evbuf, &tag, tmp) == -1'
271 ' || tag != need_tag)\n'
274 ' if (%(name)s_unmarshal(msg, tmp) == -1)\n'
280 ' evbuffer_free(tmp);\n'
282 '}\n' ) % { 'name' : self
._name
}
284 # Complete message marshaling
287 'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, '
288 'const struct %(name)s *msg)\n'
290 ' struct evbuffer *_buf = evbuffer_new();\n'
291 ' assert(_buf != NULL);\n'
292 ' evbuffer_drain(_buf, -1);\n'
293 ' %(name)s_marshal(_buf, msg);\n'
294 ' evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf), '
295 'EVBUFFER_LENGTH(_buf));\n'
296 ' evbuffer_free(_buf);\n'
297 '}\n' ) % { 'name' : self
._name
}
300 def __init__(self
, type, name
, tag
):
306 self
._can
_be
_array
= 0
308 self
._line
_count
= -1
312 def GetTranslation(self
):
313 return { "parent_name" : self
._struct
.Name(),
315 "ctype" : self
._ctype
,
316 "refname" : self
._refname
319 def SetStruct(self
, struct
):
320 self
._struct
= struct
323 assert self
._line
_count
!= -1
324 return self
._line
_count
326 def SetLineCount(self
, number
):
327 self
._line
_count
= number
333 return self
._optional
344 def MakeArray(self
, yes
=1):
347 def MakeOptional(self
):
350 def GetFuncName(self
):
351 return '%s_%s_get' % (self
._struct
.Name(), self
._name
)
353 def GetDeclaration(self
, funcname
):
354 code
= [ 'int %s(struct %s *, %s *);' % (
355 funcname
, self
._struct
.Name(), self
._ctype
) ]
361 '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, '
364 ' if (msg->%(name)s_set != 1)',
366 ' *value = msg->%(name)s_data;',
369 code
= '\n'.join(code
)
370 code
= code
% self
.GetTranslation()
371 return code
.split('\n')
373 def AssignFuncName(self
):
374 return '%s_%s_assign' % (self
._struct
.Name(), self
._name
)
376 def AddFuncName(self
):
377 return '%s_%s_add' % (self
._struct
.Name(), self
._name
)
379 def AssignDeclaration(self
, funcname
):
380 code
= [ 'int %s(struct %s *, const %s);' % (
381 funcname
, self
._struct
.Name(), self
._ctype
) ]
384 def CodeAssign(self
):
386 '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,'
387 ' const %(ctype)s value)',
389 ' msg->%(name)s_set = 1;',
390 ' msg->%(name)s_data = value;',
393 code
= '\n'.join(code
)
394 code
= code
% self
.GetTranslation()
395 return code
.split('\n')
397 def CodeClear(self
, structname
):
398 code
= [ '%s->%s_set = 0;' % (structname
, self
.Name()) ]
402 def CodeComplete(self
, structname
):
406 code
= [ 'if (!%s->%s_set)' % (structname
, self
.Name()),
411 def CodeFree(self
, name
):
416 '%(parent_name)s_%(name)s_assign,',
417 '%(parent_name)s_%(name)s_get,'
420 code
.append('%(parent_name)s_%(name)s_add,')
422 code
= '\n'.join(code
)
423 code
= code
% self
.GetTranslation()
424 return code
.split('\n')
427 if self
.Array() and not self
._can
_be
_array
:
428 print >>sys
.stderr
, (
429 'Entry "%s" cannot be created as an array '
430 'around line %d' ) % (self
._name
, self
.LineCount())
433 print >>sys
.stderr
, (
434 'Entry "%s" does not know which struct it belongs to '
435 'around line %d' ) % (self
._name
, self
.LineCount())
437 if self
._optional
and self
._array
:
438 print >>sys
.stderr
, ( 'Entry "%s" has illegal combination of '
439 'optional and array around line %d' ) % (
440 self
._name
, self
.LineCount() )
443 class EntryBytes(Entry
):
444 def __init__(self
, type, name
, tag
, length
):
446 Entry
.__init
__(self
, type, name
, tag
)
448 self
._length
= length
449 self
._ctype
= 'ev_uint8_t'
451 def GetDeclaration(self
, funcname
):
452 code
= [ 'int %s(struct %s *, %s **);' % (
453 funcname
, self
._struct
.Name(), self
._ctype
) ]
456 def AssignDeclaration(self
, funcname
):
457 code
= [ 'int %s(struct %s *, const %s *);' % (
458 funcname
, self
._struct
.Name(), self
._ctype
) ]
461 def Declaration(self
):
462 dcl
= ['ev_uint8_t %s_data[%s];' % (self
._name
, self
._length
)]
469 '%s_%s_get(struct %s *msg, %s **value)' % (
470 self
._struct
.Name(), name
,
471 self
._struct
.Name(), self
._ctype
),
473 ' if (msg->%s_set != 1)' % name
,
475 ' *value = msg->%s_data;' % name
,
480 def CodeAssign(self
):
483 '%s_%s_assign(struct %s *msg, const %s *value)' % (
484 self
._struct
.Name(), name
,
485 self
._struct
.Name(), self
._ctype
),
487 ' msg->%s_set = 1;' % name
,
488 ' memcpy(msg->%s_data, value, %s);' % (
494 def CodeUnmarshal(self
, buf
, tag_name
, var_name
):
495 code
= [ 'if (evtag_unmarshal_fixed(%s, %s, ' % (buf
, tag_name
) +
496 '%s->%s_data, ' % (var_name
, self
._name
) +
497 'sizeof(%s->%s_data)) == -1) {' % (
498 var_name
, self
._name
),
499 ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
506 def CodeMarshal(self
, buf
, tag_name
, var_name
):
507 code
= ['evtag_marshal(%s, %s, %s->%s_data, sizeof(%s->%s_data));' % (
508 buf
, tag_name
, var_name
, self
._name
, var_name
, self
._name
)]
511 def CodeClear(self
, structname
):
512 code
= [ '%s->%s_set = 0;' % (structname
, self
.Name()),
513 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
514 structname
, self
._name
, structname
, self
._name
)]
518 def CodeNew(self
, name
):
519 code
= ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
520 name
, self
._name
, name
, self
._name
)]
525 print >>sys
.stderr
, 'Entry "%s" needs a length around line %d' % (
526 self
._name
, self
.LineCount() )
531 class EntryInt(Entry
):
532 def __init__(self
, type, name
, tag
):
534 Entry
.__init
__(self
, type, name
, tag
)
536 self
._ctype
= 'ev_uint32_t'
538 def CodeUnmarshal(self
, buf
, tag_name
, var_name
):
539 code
= ['if (evtag_unmarshal_int(%s, %s, &%s->%s_data) == -1) {' % (
540 buf
, tag_name
, var_name
, self
._name
),
541 ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
547 def CodeMarshal(self
, buf
, tag_name
, var_name
):
548 code
= ['evtag_marshal_int(%s, %s, %s->%s_data);' % (
549 buf
, tag_name
, var_name
, self
._name
)]
552 def Declaration(self
):
553 dcl
= ['ev_uint32_t %s_data;' % self
._name
]
557 def CodeNew(self
, name
):
558 code
= ['%s->%s_data = 0;' % (name
, self
._name
)]
561 class EntryString(Entry
):
562 def __init__(self
, type, name
, tag
):
564 Entry
.__init
__(self
, type, name
, tag
)
566 self
._ctype
= 'char *'
568 def CodeAssign(self
):
571 %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
572 const %(ctype)s value)
574 if (msg->%(name)s_data != NULL)
575 free(msg->%(name)s_data);
576 if ((msg->%(name)s_data = strdup(value)) == NULL)
578 msg->%(name)s_set = 1;
580 }""" % self
.GetTranslation()
582 return code
.split('\n')
584 def CodeUnmarshal(self
, buf
, tag_name
, var_name
):
585 code
= ['if (evtag_unmarshal_string(%s, %s, &%s->%s_data) == -1) {' % (
586 buf
, tag_name
, var_name
, self
._name
),
587 ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
594 def CodeMarshal(self
, buf
, tag_name
, var_name
):
595 code
= ['evtag_marshal_string(%s, %s, %s->%s_data);' % (
596 buf
, tag_name
, var_name
, self
._name
)]
599 def CodeClear(self
, structname
):
600 code
= [ 'if (%s->%s_set == 1) {' % (structname
, self
.Name()),
601 ' free (%s->%s_data);' % (structname
, self
.Name()),
602 ' %s->%s_data = NULL;' % (structname
, self
.Name()),
603 ' %s->%s_set = 0;' % (structname
, self
.Name()),
609 def CodeNew(self
, name
):
610 code
= ['%s->%s_data = NULL;' % (name
, self
._name
)]
613 def CodeFree(self
, name
):
614 code
= ['if (%s->%s_data != NULL)' % (name
, self
._name
),
615 ' free (%s->%s_data); ' % (name
, self
._name
)]
619 def Declaration(self
):
620 dcl
= ['char *%s_data;' % self
._name
]
624 class EntryStruct(Entry
):
625 def __init__(self
, type, name
, tag
, refname
):
627 Entry
.__init
__(self
, type, name
, tag
)
629 self
._can
_be
_array
= 1
630 self
._refname
= refname
631 self
._ctype
= 'struct %s*' % refname
636 '%s_%s_get(struct %s *msg, %s *value)' % (
637 self
._struct
.Name(), name
,
638 self
._struct
.Name(), self
._ctype
),
640 ' if (msg->%s_set != 1) {' % name
,
641 ' msg->%s_data = %s_new();' % (name
, self
._refname
),
642 ' if (msg->%s_data == NULL)' % name
,
644 ' msg->%s_set = 1;' % name
,
646 ' *value = msg->%s_data;' % name
,
651 def CodeAssign(self
):
654 %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
655 const %(ctype)s value)
657 struct evbuffer *tmp = NULL;
658 if (msg->%(name)s_set) {
659 %(refname)s_clear(msg->%(name)s_data);
660 msg->%(name)s_set = 0;
662 msg->%(name)s_data = %(refname)s_new();
663 if (msg->%(name)s_data == NULL) {
664 event_warn("%%s: %(refname)s_new()", __func__);
668 if ((tmp = evbuffer_new()) == NULL) {
669 event_warn("%%s: evbuffer_new()", __func__);
672 %(refname)s_marshal(tmp, value);
673 if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) {
674 event_warnx("%%s: %(refname)s_unmarshal", __func__);
677 msg->%(name)s_set = 1;
683 if (msg->%(name)s_data != NULL) {
684 %(refname)s_free(msg->%(name)s_data);
685 msg->%(name)s_data = NULL;
688 }""" % self
.GetTranslation()
689 return code
.split('\n')
691 def CodeComplete(self
, structname
):
693 code
= [ 'if (%s->%s_set && %s_complete(%s->%s_data) == -1)' % (
694 structname
, self
.Name(),
695 self
._refname
, structname
, self
.Name()),
698 code
= [ 'if (%s_complete(%s->%s_data) == -1)' % (
699 self
._refname
, structname
, self
.Name()),
704 def CodeUnmarshal(self
, buf
, tag_name
, var_name
):
705 code
= ['%s->%s_data = %s_new();' % (
706 var_name
, self
._name
, self
._refname
),
707 'if (%s->%s_data == NULL)' % (var_name
, self
._name
),
709 'if (evtag_unmarshal_%s(%s, %s, %s->%s_data) == -1) {' % (
710 self
._refname
, buf
, tag_name
, var_name
, self
._name
),
711 ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
718 def CodeMarshal(self
, buf
, tag_name
, var_name
):
719 code
= ['evtag_marshal_%s(%s, %s, %s->%s_data);' % (
720 self
._refname
, buf
, tag_name
, var_name
, self
._name
)]
723 def CodeClear(self
, structname
):
724 code
= [ 'if (%s->%s_set == 1) {' % (structname
, self
.Name()),
725 ' %s_free(%s->%s_data);' % (
726 self
._refname
, structname
, self
.Name()),
727 ' %s->%s_data = NULL;' % (structname
, self
.Name()),
728 ' %s->%s_set = 0;' % (structname
, self
.Name()),
734 def CodeNew(self
, name
):
735 code
= ['%s->%s_data = NULL;' % (name
, self
._name
)]
738 def CodeFree(self
, name
):
739 code
= ['if (%s->%s_data != NULL)' % (name
, self
._name
),
740 ' %s_free(%s->%s_data); ' % (
741 self
._refname
, name
, self
._name
)]
745 def Declaration(self
):
746 dcl
= ['%s %s_data;' % (self
._ctype
, self
._name
)]
750 class EntryVarBytes(Entry
):
751 def __init__(self
, type, name
, tag
):
753 Entry
.__init
__(self
, type, name
, tag
)
755 self
._ctype
= 'ev_uint8_t *'
757 def GetDeclaration(self
, funcname
):
758 code
= [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % (
759 funcname
, self
._struct
.Name(), self
._ctype
) ]
762 def AssignDeclaration(self
, funcname
):
763 code
= [ 'int %s(struct %s *, const %s, ev_uint32_t);' % (
764 funcname
, self
._struct
.Name(), self
._ctype
) ]
767 def CodeAssign(self
):
770 '%s_%s_assign(struct %s *msg, '
771 'const %s value, ev_uint32_t len)' % (
772 self
._struct
.Name(), name
,
773 self
._struct
.Name(), self
._ctype
),
775 ' if (msg->%s_data != NULL)' % name
,
776 ' free (msg->%s_data);' % name
,
777 ' msg->%s_data = malloc(len);' % name
,
778 ' if (msg->%s_data == NULL)' % name
,
780 ' msg->%s_set = 1;' % name
,
781 ' msg->%s_length = len;' % name
,
782 ' memcpy(msg->%s_data, value, len);' % name
,
790 '%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)' % (
791 self
._struct
.Name(), name
,
792 self
._struct
.Name(), self
._ctype
),
794 ' if (msg->%s_set != 1)' % name
,
796 ' *value = msg->%s_data;' % name
,
797 ' *plen = msg->%s_length;' % name
,
802 def CodeUnmarshal(self
, buf
, tag_name
, var_name
):
803 code
= ['if (evtag_payload_length(%s, &%s->%s_length) == -1)' % (
804 buf
, var_name
, self
._name
),
806 # We do not want DoS opportunities
807 'if (%s->%s_length > EVBUFFER_LENGTH(%s))' % (
808 var_name
, self
._name
, buf
),
810 'if ((%s->%s_data = malloc(%s->%s_length)) == NULL)' % (
811 var_name
, self
._name
, var_name
, self
._name
),
813 'if (evtag_unmarshal_fixed(%s, %s, %s->%s_data, '
814 '%s->%s_length) == -1) {' % (
815 buf
, tag_name
, var_name
, self
._name
, var_name
, self
._name
),
816 ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
823 def CodeMarshal(self
, buf
, tag_name
, var_name
):
824 code
= ['evtag_marshal(%s, %s, %s->%s_data, %s->%s_length);' % (
825 buf
, tag_name
, var_name
, self
._name
, var_name
, self
._name
)]
828 def CodeClear(self
, structname
):
829 code
= [ 'if (%s->%s_set == 1) {' % (structname
, self
.Name()),
830 ' free (%s->%s_data);' % (structname
, self
.Name()),
831 ' %s->%s_data = NULL;' % (structname
, self
.Name()),
832 ' %s->%s_length = 0;' % (structname
, self
.Name()),
833 ' %s->%s_set = 0;' % (structname
, self
.Name()),
839 def CodeNew(self
, name
):
840 code
= ['%s->%s_data = NULL;' % (name
, self
._name
),
841 '%s->%s_length = 0;' % (name
, self
._name
) ]
844 def CodeFree(self
, name
):
845 code
= ['if (%s->%s_data != NULL)' % (name
, self
._name
),
846 ' free (%s->%s_data); ' % (name
, self
._name
)]
850 def Declaration(self
):
851 dcl
= ['ev_uint8_t *%s_data;' % self
._name
,
852 'ev_uint32_t %s_length;' % self
._name
]
856 class EntryArray(Entry
):
857 def __init__(self
, entry
):
859 Entry
.__init
__(self
, entry
._type
, entry
._name
, entry
._tag
)
862 self
._refname
= entry
._refname
863 self
._ctype
= 'struct %s *' % self
._refname
865 def GetDeclaration(self
, funcname
):
866 """Allows direct access to elements of the array."""
867 translate
= self
.GetTranslation()
868 translate
["funcname"] = funcname
870 'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' %
874 def AssignDeclaration(self
, funcname
):
875 code
= [ 'int %s(struct %s *, int, const %s);' % (
876 funcname
, self
._struct
.Name(), self
._ctype
) ]
879 def AddDeclaration(self
, funcname
):
880 code
= [ '%s %s(struct %s *);' % (
881 self
._ctype
, funcname
, self
._struct
.Name() ) ]
886 %(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset,
889 if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length)
891 *value = msg->%(name)s_data[offset];
893 }""" % self
.GetTranslation()
895 return code
.split('\n')
897 def CodeAssign(self
):
899 %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,
900 const %(ctype)s value)
902 struct evbuffer *tmp = NULL;
903 if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)
905 %(refname)s_clear(msg->%(name)s_data[off]);
906 if ((tmp = evbuffer_new()) == NULL) {
907 event_warn("%%s: evbuffer_new()", __func__);
910 %(refname)s_marshal(tmp, value);
911 if (%(refname)s_unmarshal(msg->%(name)s_data[off], tmp) == -1) {
912 event_warnx("%%s: %(refname)s_unmarshal", __func__);
920 %(refname)s_clear(msg->%(name)s_data[off]);
922 }""" % self
.GetTranslation()
924 return code
.split('\n')
929 %(parent_name)s_%(name)s_add(struct %(parent_name)s *msg)
931 if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {
932 int tobe_allocated = msg->%(name)s_num_allocated;
933 %(ctype)s* new_data = NULL;
934 tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;
935 new_data = (%(ctype)s*) realloc(msg->%(name)s_data,
936 tobe_allocated * sizeof(%(ctype)s));
937 if (new_data == NULL)
939 msg->%(name)s_data = new_data;
940 msg->%(name)s_num_allocated = tobe_allocated;
942 msg->%(name)s_data[msg->%(name)s_length - 1] = %(refname)s_new();
943 if (msg->%(name)s_data[msg->%(name)s_length - 1] == NULL)
945 msg->%(name)s_set = 1;
946 return (msg->%(name)s_data[msg->%(name)s_length - 1]);
948 --msg->%(name)s_length;
951 """ % self
.GetTranslation()
953 return code
.split('\n')
955 def CodeComplete(self
, structname
):
957 translate
= self
.GetTranslation()
960 code
.append( 'if (%(structname)s->%(name)s_set)' % translate
)
962 translate
["structname"] = structname
965 for (i = 0; i < %(structname)s->%(name)s_length; ++i) {
966 if (%(refname)s_complete(%(structname)s->%(name)s_data[i]) == -1)
970 code
.extend(tmp
.split('\n'))
974 def CodeUnmarshal(self
, buf
, tag_name
, var_name
):
975 translate
= self
.GetTranslation()
976 translate
["var_name"] = var_name
977 translate
["buf"] = buf
978 translate
["tag_name"] = tag_name
979 code
= """if (%(parent_name)s_%(name)s_add(%(var_name)s) == NULL)
981 if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag_name)s,
982 %(var_name)s->%(name)s_data[%(var_name)s->%(name)s_length - 1]) == -1) {
983 --%(var_name)s->%(name)s_length;
984 event_warnx("%%s: failed to unmarshal %(name)s", __func__);
988 return code
.split('\n')
990 def CodeMarshal(self
, buf
, tag_name
, var_name
):
993 ' for (i = 0; i < %s->%s_length; ++i) {' % (
994 var_name
, self
._name
),
995 ' evtag_marshal_%s(%s, %s, %s->%s_data[i]);' % (
996 self
._refname
, buf
, tag_name
, var_name
, self
._name
),
1002 def CodeClear(self
, structname
):
1003 code
= [ 'if (%s->%s_set == 1) {' % (structname
, self
.Name()),
1005 ' for (i = 0; i < %s->%s_length; ++i) {' % (
1006 structname
, self
.Name()),
1007 ' %s_free(%s->%s_data[i]);' % (
1008 self
._refname
, structname
, self
.Name()),
1010 ' free(%s->%s_data);' % (structname
, self
.Name()),
1011 ' %s->%s_data = NULL;' % (structname
, self
.Name()),
1012 ' %s->%s_set = 0;' % (structname
, self
.Name()),
1013 ' %s->%s_length = 0;' % (structname
, self
.Name()),
1014 ' %s->%s_num_allocated = 0;' % (structname
, self
.Name()),
1020 def CodeNew(self
, name
):
1021 code
= ['%s->%s_data = NULL;' % (name
, self
._name
),
1022 '%s->%s_length = 0;' % (name
, self
._name
),
1023 '%s->%s_num_allocated = 0;' % (name
, self
._name
)]
1026 def CodeFree(self
, name
):
1027 code
= ['if (%s->%s_data != NULL) {' % (name
, self
._name
),
1029 ' for (i = 0; i < %s->%s_length; ++i) {' % (
1031 ' %s_free(%s->%s_data[i]); ' % (
1032 self
._refname
, name
, self
._name
),
1033 ' %s->%s_data[i] = NULL;' % (name
, self
._name
),
1035 ' free(%s->%s_data);' % (name
, self
._name
),
1036 ' %s->%s_data = NULL;' % (name
, self
._name
),
1037 ' %s->%s_length = 0;' % (name
, self
._name
),
1038 ' %s->%s_num_allocated = 0;' % (name
, self
._name
),
1044 def Declaration(self
):
1045 dcl
= ['struct %s **%s_data;' % (self
._refname
, self
._name
),
1046 'int %s_length;' % self
._name
,
1047 'int %s_num_allocated;' % self
._name
]
1051 def NormalizeLine(line
):
1055 line
= cppcomment
.sub('', line
)
1057 line
= white
.sub(' ', line
)
1061 def ProcessOneEntry(newstruct
, entry
):
1071 tokens
= entry
.split(' ')
1077 if not optional
and token
== 'optional':
1081 if not array
and token
== 'array':
1090 res
= re
.match(r
'^([^\[\]]+)(\[.*\])?$', token
)
1092 print >>sys
.stderr
, 'Cannot parse name: \"%s\" around %d' % (
1096 fixed_length
= res
.group(2)
1098 fixed_length
= fixed_length
[1:-1]
1103 if separator
!= '=':
1104 print >>sys
.stderr
, 'Expected "=" after name \"%s\" got %s' % (
1111 if not re
.match(r
'^(0x)?[0-9]+$', token
):
1112 print >>sys
.stderr
, 'Expected tag number: \"%s\"' % entry
1117 print >>sys
.stderr
, 'Cannot parse \"%s\"' % entry
1121 print >>sys
.stderr
, 'Need tag number: \"%s\"' % entry
1124 # Create the right entry
1125 if entry_type
== 'bytes':
1127 newentry
= EntryBytes(entry_type
, name
, tag
, fixed_length
)
1129 newentry
= EntryVarBytes(entry_type
, name
, tag
)
1130 elif entry_type
== 'int' and not fixed_length
:
1131 newentry
= EntryInt(entry_type
, name
, tag
)
1132 elif entry_type
== 'string' and not fixed_length
:
1133 newentry
= EntryString(entry_type
, name
, tag
)
1135 res
= re
.match(r
'^struct\[(%s)\]$' % _STRUCT_RE
,
1136 entry_type
, re
.IGNORECASE
)
1138 # References another struct defined in our file
1139 newentry
= EntryStruct(entry_type
, name
, tag
, res
.group(1))
1141 print >>sys
.stderr
, 'Bad type: "%s" in "%s"' % (entry_type
, entry
)
1147 newentry
.MakeOptional()
1149 newentry
.MakeArray()
1151 newentry
.SetStruct(newstruct
)
1152 newentry
.SetLineCount(line_count
)
1156 # We need to encapsulate this entry into a struct
1157 newname
= newentry
.Name()+ '_array'
1159 # Now borgify the new entry.
1160 newentry
= EntryArray(newentry
)
1161 newentry
.SetStruct(newstruct
)
1162 newentry
.SetLineCount(line_count
)
1163 newentry
.MakeArray()
1165 newstruct
.AddEntry(newentry
)
1169 def ProcessStruct(data
):
1170 tokens
= data
.split(' ')
1172 # First three tokens are: 'struct' 'name' '{'
1173 newstruct
= Struct(tokens
[1])
1175 inside
= ' '.join(tokens
[3:-1])
1177 tokens
= inside
.split(';')
1181 for entry
in tokens
:
1182 entry
= NormalizeLine(entry
)
1186 # It's possible that new structs get defined in here
1187 structs
.extend(ProcessOneEntry(newstruct
, entry
))
1189 structs
.append(newstruct
)
1192 def GetNextStruct(file):
1198 processed_lines
= []
1203 line
= file.readline()
1210 if not have_c_comment
and re
.search(r
'/\*', line
):
1211 if re
.search(r
'/\*.*\*/', line
):
1212 line
= re
.sub(r
'/\*.*\*/', '', line
)
1214 line
= re
.sub(r
'/\*.*$', '', line
)
1218 if not re
.search(r
'\*/', line
):
1221 line
= re
.sub(r
'^.*\*/', '', line
)
1223 line
= NormalizeLine(line
)
1229 if re
.match(r
'#include ["<].*[>"]', line
):
1230 cppdirect
.append(line
)
1233 if re
.match(r
'^#(if( |def)|endif)', line
):
1234 cppdirect
.append(line
)
1237 if re
.match(r
'^#define', line
):
1238 headerdirect
.append(line
)
1241 if not re
.match(r
'^struct %s {$' % _STRUCT_RE
,
1242 line
, re
.IGNORECASE
):
1243 print >>sys
.stderr
, 'Missing struct on line %d: %s' % (
1251 # We are inside the struct
1252 tokens
= line
.split('}')
1253 if len(tokens
) == 1:
1258 print >>sys
.stderr
, 'Trailing garbage after struct on line %d' % (
1262 # We found the end of the struct
1263 data
+= ' %s}' % tokens
[0]
1266 # Remove any comments, that might be in there
1267 data
= re
.sub(r
'/\*.*\*/', '', data
)
1274 Parses the input file and returns C code and corresponding header file.
1280 # Just gets the whole struct nicely formatted
1281 data
= GetNextStruct(file)
1286 entities
.extend(ProcessStruct(data
))
1290 def GuardName(name
):
1291 name
= '_'.join(name
.split('.'))
1292 name
= '_'.join(name
.split('/'))
1293 guard
= '_'+name
.upper()+'_'
1297 def HeaderPreamble(name
):
1298 guard
= GuardName(name
)
1301 ' * Automatically generated from %s\n'
1304 '#define %s\n\n' ) % (
1307 # insert stdint.h - let's hope everyone has it
1309 '#include <event-config.h>\n'
1310 '#ifdef _EVENT_HAVE_STDINT_H\n'
1311 '#include <stdint.h>\n'
1314 for statement
in headerdirect
:
1315 pre
+= '%s\n' % statement
1320 '#define EVTAG_HAS(msg, member) ((msg)->member##_set == 1)\n'
1322 '#define EVTAG_ASSIGN(msg, member, args...) '
1323 '(*(msg)->base->member##_assign)(msg, ## args)\n'
1324 '#define EVTAG_GET(msg, member, args...) '
1325 '(*(msg)->base->member##_get)(msg, ## args)\n'
1327 '#define EVTAG_ASSIGN(msg, member, ...) '
1328 '(*(msg)->base->member##_assign)(msg, ## __VA_ARGS__)\n'
1329 '#define EVTAG_GET(msg, member, ...) '
1330 '(*(msg)->base->member##_get)(msg, ## __VA_ARGS__)\n'
1332 '#define EVTAG_ADD(msg, member) (*(msg)->base->member##_add)(msg)\n'
1333 '#define EVTAG_LEN(msg, member) ((msg)->member##_length)\n'
1339 def HeaderPostamble(name
):
1340 guard
= GuardName(name
)
1341 return '#endif /* %s */' % guard
1343 def BodyPreamble(name
):
1347 header_file
= '.'.join(name
.split('.')[:-1]) + '.gen.h'
1350 ' * Automatically generated from %s\n'
1351 ' * by %s/%s. DO NOT EDIT THIS FILE.\n'
1352 ' */\n\n' ) % (name
, _NAME
, _VERSION
)
1353 pre
+= ( '#include <sys/types.h>\n'
1354 '#ifdef _EVENT_HAVE_SYS_TIME_H\n'
1355 '#include <sys/time.h>\n'
1357 '#include <stdlib.h>\n'
1358 '#include <string.h>\n'
1359 '#include <assert.h>\n'
1360 '#define EVENT_NO_STRUCT\n'
1361 '#include <event.h>\n\n'
1362 '#ifdef _EVENT___func__\n'
1363 '#define __func__ _EVENT___func__\n'
1366 for statement
in cppdirect
:
1367 pre
+= '%s\n' % statement
1369 pre
+= '\n#include "%s"\n\n' % header_file
1371 pre
+= 'void event_err(int eval, const char *fmt, ...);\n'
1372 pre
+= 'void event_warn(const char *fmt, ...);\n'
1373 pre
+= 'void event_errx(int eval, const char *fmt, ...);\n'
1374 pre
+= 'void event_warnx(const char *fmt, ...);\n\n'
1379 if len(argv
) < 2 or not argv
[1]:
1380 print >>sys
.stderr
, 'Need RPC description file as first argument.'
1385 ext
= filename
.split('.')[-1]
1387 print >>sys
.stderr
, 'Unrecognized file extension: %s' % ext
1390 print >>sys
.stderr
, 'Reading \"%s\"' % filename
1392 fp
= open(filename
, 'r')
1393 entities
= Parse(fp
)
1396 header_file
= '.'.join(filename
.split('.')[:-1]) + '.gen.h'
1397 impl_file
= '.'.join(filename
.split('.')[:-1]) + '.gen.c'
1399 print >>sys
.stderr
, '... creating "%s"' % header_file
1400 header_fp
= open(header_file
, 'w')
1401 print >>header_fp
, HeaderPreamble(filename
)
1403 # Create forward declarations: allows other structs to reference
1405 for entry
in entities
:
1406 entry
.PrintForwardDeclaration(header_fp
)
1407 print >>header_fp
, ''
1409 for entry
in entities
:
1410 entry
.PrintTags(header_fp
)
1411 entry
.PrintDeclaration(header_fp
)
1412 print >>header_fp
, HeaderPostamble(filename
)
1415 print >>sys
.stderr
, '... creating "%s"' % impl_file
1416 impl_fp
= open(impl_file
, 'w')
1417 print >>impl_fp
, BodyPreamble(filename
)
1418 for entry
in entities
:
1419 entry
.PrintCode(impl_fp
)
1422 if __name__
== '__main__':