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