xref: /freebsd/contrib/ntp/sntp/libevent/event_rpcgen.py (revision a466cc55373fc3cf86837f09da729535b57e69a1)
1*a466cc55SCy Schubert#!/usr/bin/env python
22b15cb3dSCy Schubert#
32b15cb3dSCy Schubert# Copyright (c) 2005-2007 Niels Provos <provos@citi.umich.edu>
42b15cb3dSCy Schubert# Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
52b15cb3dSCy Schubert# All rights reserved.
62b15cb3dSCy Schubert#
72b15cb3dSCy Schubert# Generates marshaling code based on libevent.
82b15cb3dSCy Schubert
9*a466cc55SCy Schubert# pylint: disable=too-many-lines
10*a466cc55SCy Schubert# pylint: disable=too-many-branches
11*a466cc55SCy Schubert# pylint: disable=too-many-public-methods
12*a466cc55SCy Schubert# pylint: disable=too-many-statements
13*a466cc55SCy Schubert# pylint: disable=global-statement
142b15cb3dSCy Schubert
15*a466cc55SCy Schubert# TODO:
16*a466cc55SCy Schubert# 1) propagate the arguments/options parsed by argparse down to the
17*a466cc55SCy Schubert#    instantiated factory objects.
18*a466cc55SCy Schubert# 2) move the globals into a class that manages execution, including the
19*a466cc55SCy Schubert#    progress outputs that go to stderr at the moment.
20*a466cc55SCy Schubert# 3) emit other languages.
21*a466cc55SCy Schubert
22*a466cc55SCy Schubertimport argparse
232b15cb3dSCy Schubertimport re
24*a466cc55SCy Schubertimport sys
252b15cb3dSCy Schubert
262b15cb3dSCy Schubert_NAME = "event_rpcgen.py"
272b15cb3dSCy Schubert_VERSION = "0.1"
282b15cb3dSCy Schubert
292b15cb3dSCy Schubert# Globals
30*a466cc55SCy SchubertLINE_COUNT = 0
312b15cb3dSCy Schubert
32*a466cc55SCy SchubertCPPCOMMENT_RE = re.compile(r"\/\/.*$")
33*a466cc55SCy SchubertNONIDENT_RE = re.compile(r"\W")
34*a466cc55SCy SchubertPREPROCESSOR_DEF_RE = re.compile(r"^#define")
35*a466cc55SCy SchubertSTRUCT_REF_RE = re.compile(r"^struct\[(?P<name>[a-zA-Z_][a-zA-Z0-9_]*)\]$")
36*a466cc55SCy SchubertSTRUCT_DEF_RE = re.compile(r"^struct +[a-zA-Z_][a-zA-Z0-9_]* *{$")
37*a466cc55SCy SchubertWHITESPACE_RE = re.compile(r"\s+")
382b15cb3dSCy Schubert
39*a466cc55SCy SchubertHEADER_DIRECT = []
40*a466cc55SCy SchubertCPP_DIRECT = []
412b15cb3dSCy Schubert
42*a466cc55SCy SchubertQUIETLY = False
43*a466cc55SCy Schubert
442b15cb3dSCy Schubert
452b15cb3dSCy Schubertdef declare(s):
462b15cb3dSCy Schubert    if not QUIETLY:
47*a466cc55SCy Schubert        print(s)
48*a466cc55SCy Schubert
492b15cb3dSCy Schubert
502b15cb3dSCy Schubertdef TranslateList(mylist, mydict):
51*a466cc55SCy Schubert    return [x % mydict for x in mylist]
522b15cb3dSCy Schubert
53*a466cc55SCy Schubert
542b15cb3dSCy Schubertclass RpcGenError(Exception):
55*a466cc55SCy Schubert    """An Exception class for parse errors."""
56*a466cc55SCy Schubert
57*a466cc55SCy Schubert    def __init__(self, why): # pylint: disable=super-init-not-called
582b15cb3dSCy Schubert        self.why = why
59*a466cc55SCy Schubert
602b15cb3dSCy Schubert    def __str__(self):
612b15cb3dSCy Schubert        return str(self.why)
622b15cb3dSCy Schubert
63*a466cc55SCy Schubert
642b15cb3dSCy Schubert# Holds everything that makes a struct
65*a466cc55SCy Schubertclass Struct(object):
662b15cb3dSCy Schubert    def __init__(self, name):
672b15cb3dSCy Schubert        self._name = name
682b15cb3dSCy Schubert        self._entries = []
692b15cb3dSCy Schubert        self._tags = {}
70*a466cc55SCy Schubert        declare("  Created struct: %s" % name)
712b15cb3dSCy Schubert
722b15cb3dSCy Schubert    def AddEntry(self, entry):
73*a466cc55SCy Schubert        if entry.Tag() in self._tags:
742b15cb3dSCy Schubert            raise RpcGenError(
752b15cb3dSCy Schubert                'Entry "%s" duplicates tag number %d from "%s" '
76*a466cc55SCy Schubert                "around line %d"
77*a466cc55SCy Schubert                % (entry.Name(), entry.Tag(), self._tags[entry.Tag()], LINE_COUNT)
78*a466cc55SCy Schubert            )
792b15cb3dSCy Schubert        self._entries.append(entry)
802b15cb3dSCy Schubert        self._tags[entry.Tag()] = entry.Name()
81*a466cc55SCy Schubert        declare("    Added entry: %s" % entry.Name())
822b15cb3dSCy Schubert
832b15cb3dSCy Schubert    def Name(self):
842b15cb3dSCy Schubert        return self._name
852b15cb3dSCy Schubert
862b15cb3dSCy Schubert    def EntryTagName(self, entry):
872b15cb3dSCy Schubert        """Creates the name inside an enumeration for distinguishing data
882b15cb3dSCy Schubert        types."""
892b15cb3dSCy Schubert        name = "%s_%s" % (self._name, entry.Name())
902b15cb3dSCy Schubert        return name.upper()
912b15cb3dSCy Schubert
92*a466cc55SCy Schubert    @staticmethod
93*a466cc55SCy Schubert    def PrintIndented(filep, ident, code):
942b15cb3dSCy Schubert        """Takes an array, add indentation to each entry and prints it."""
952b15cb3dSCy Schubert        for entry in code:
96*a466cc55SCy Schubert            filep.write("%s%s\n" % (ident, entry))
97*a466cc55SCy Schubert
982b15cb3dSCy Schubert
992b15cb3dSCy Schubertclass StructCCode(Struct):
1002b15cb3dSCy Schubert    """ Knows how to generate C code for a struct """
1012b15cb3dSCy Schubert
1022b15cb3dSCy Schubert    def __init__(self, name):
1032b15cb3dSCy Schubert        Struct.__init__(self, name)
1042b15cb3dSCy Schubert
105*a466cc55SCy Schubert    def PrintTags(self, filep):
1062b15cb3dSCy Schubert        """Prints the tag definitions for a structure."""
107*a466cc55SCy Schubert        filep.write("/* Tag definition for %s */\n" % self._name)
108*a466cc55SCy Schubert        filep.write("enum %s_ {\n" % self._name.lower())
1092b15cb3dSCy Schubert        for entry in self._entries:
110*a466cc55SCy Schubert            filep.write("  %s=%d,\n" % (self.EntryTagName(entry), entry.Tag()))
111*a466cc55SCy Schubert        filep.write("  %s_MAX_TAGS\n" % (self._name.upper()))
112*a466cc55SCy Schubert        filep.write("};\n\n")
1132b15cb3dSCy Schubert
114*a466cc55SCy Schubert    def PrintForwardDeclaration(self, filep):
115*a466cc55SCy Schubert        filep.write("struct %s;\n" % self._name)
1162b15cb3dSCy Schubert
117*a466cc55SCy Schubert    def PrintDeclaration(self, filep):
118*a466cc55SCy Schubert        filep.write("/* Structure declaration for %s */\n" % self._name)
119*a466cc55SCy Schubert        filep.write("struct %s_access_ {\n" % self._name)
1202b15cb3dSCy Schubert        for entry in self._entries:
121*a466cc55SCy Schubert            dcl = entry.AssignDeclaration("(*%s_assign)" % entry.Name())
122*a466cc55SCy Schubert            dcl.extend(entry.GetDeclaration("(*%s_get)" % entry.Name()))
1232b15cb3dSCy Schubert            if entry.Array():
124*a466cc55SCy Schubert                dcl.extend(entry.AddDeclaration("(*%s_add)" % entry.Name()))
125*a466cc55SCy Schubert            self.PrintIndented(filep, "  ", dcl)
126*a466cc55SCy Schubert        filep.write("};\n\n")
1272b15cb3dSCy Schubert
128*a466cc55SCy Schubert        filep.write("struct %s {\n" % self._name)
129*a466cc55SCy Schubert        filep.write("  struct %s_access_ *base;\n\n" % self._name)
1302b15cb3dSCy Schubert        for entry in self._entries:
1312b15cb3dSCy Schubert            dcl = entry.Declaration()
132*a466cc55SCy Schubert            self.PrintIndented(filep, "  ", dcl)
133*a466cc55SCy Schubert        filep.write("\n")
1342b15cb3dSCy Schubert        for entry in self._entries:
135*a466cc55SCy Schubert            filep.write("  ev_uint8_t %s_set;\n" % entry.Name())
136*a466cc55SCy Schubert        filep.write("};\n\n")
1372b15cb3dSCy Schubert
138*a466cc55SCy Schubert        filep.write(
1392b15cb3dSCy Schubert            """struct %(name)s *%(name)s_new(void);
1402b15cb3dSCy Schubertstruct %(name)s *%(name)s_new_with_arg(void *);
1412b15cb3dSCy Schubertvoid %(name)s_free(struct %(name)s *);
1422b15cb3dSCy Schubertvoid %(name)s_clear(struct %(name)s *);
1432b15cb3dSCy Schubertvoid %(name)s_marshal(struct evbuffer *, const struct %(name)s *);
1442b15cb3dSCy Schubertint %(name)s_unmarshal(struct %(name)s *, struct evbuffer *);
1452b15cb3dSCy Schubertint %(name)s_complete(struct %(name)s *);
1462b15cb3dSCy Schubertvoid evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t,
1472b15cb3dSCy Schubert    const struct %(name)s *);
1482b15cb3dSCy Schubertint evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
149*a466cc55SCy Schubert    struct %(name)s *);\n"""
150*a466cc55SCy Schubert            % {"name": self._name}
151*a466cc55SCy Schubert        )
1522b15cb3dSCy Schubert
1532b15cb3dSCy Schubert        # Write a setting function of every variable
1542b15cb3dSCy Schubert        for entry in self._entries:
155*a466cc55SCy Schubert            self.PrintIndented(
156*a466cc55SCy Schubert                filep, "", entry.AssignDeclaration(entry.AssignFuncName())
157*a466cc55SCy Schubert            )
158*a466cc55SCy Schubert            self.PrintIndented(filep, "", entry.GetDeclaration(entry.GetFuncName()))
1592b15cb3dSCy Schubert            if entry.Array():
160*a466cc55SCy Schubert                self.PrintIndented(filep, "", entry.AddDeclaration(entry.AddFuncName()))
1612b15cb3dSCy Schubert
162*a466cc55SCy Schubert        filep.write("/* --- %s done --- */\n\n" % self._name)
1632b15cb3dSCy Schubert
164*a466cc55SCy Schubert    def PrintCode(self, filep):
165*a466cc55SCy Schubert        filep.write(
166*a466cc55SCy Schubert            """/*
167*a466cc55SCy Schubert * Implementation of %s
168*a466cc55SCy Schubert */
169*a466cc55SCy Schubert"""
170*a466cc55SCy Schubert            % (self._name)
171*a466cc55SCy Schubert        )
1722b15cb3dSCy Schubert
173*a466cc55SCy Schubert        filep.write(
174*a466cc55SCy Schubert            """
175*a466cc55SCy Schubertstatic struct %(name)s_access_ %(name)s_base__ = {
176*a466cc55SCy Schubert"""
177*a466cc55SCy Schubert            % {"name": self._name}
178*a466cc55SCy Schubert        )
1792b15cb3dSCy Schubert        for entry in self._entries:
180*a466cc55SCy Schubert            self.PrintIndented(filep, "  ", entry.CodeBase())
181*a466cc55SCy Schubert        filep.write("};\n\n")
1822b15cb3dSCy Schubert
1832b15cb3dSCy Schubert        # Creation
184*a466cc55SCy Schubert        filep.write(
185*a466cc55SCy Schubert            """struct %(name)s *
186*a466cc55SCy Schubert%(name)s_new(void)
187*a466cc55SCy Schubert{
188*a466cc55SCy Schubert  return %(name)s_new_with_arg(NULL);
189*a466cc55SCy Schubert}
190*a466cc55SCy Schubert
191*a466cc55SCy Schubertstruct %(name)s *
192*a466cc55SCy Schubert%(name)s_new_with_arg(void *unused)
193*a466cc55SCy Schubert{
194*a466cc55SCy Schubert  struct %(name)s *tmp;
195*a466cc55SCy Schubert  if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {
196*a466cc55SCy Schubert    event_warn("%%s: malloc", __func__);
197*a466cc55SCy Schubert    return (NULL);
198*a466cc55SCy Schubert  }
199*a466cc55SCy Schubert  tmp->base = &%(name)s_base__;
200*a466cc55SCy Schubert
201*a466cc55SCy Schubert"""
202*a466cc55SCy Schubert            % {"name": self._name}
203*a466cc55SCy Schubert        )
2042b15cb3dSCy Schubert
2052b15cb3dSCy Schubert        for entry in self._entries:
206*a466cc55SCy Schubert            self.PrintIndented(filep, "  ", entry.CodeInitialize("tmp"))
207*a466cc55SCy Schubert            filep.write("  tmp->%s_set = 0;\n\n" % entry.Name())
2082b15cb3dSCy Schubert
209*a466cc55SCy Schubert        filep.write(
210*a466cc55SCy Schubert            """  return (tmp);
211*a466cc55SCy Schubert}
212*a466cc55SCy Schubert
213*a466cc55SCy Schubert"""
214*a466cc55SCy Schubert        )
2152b15cb3dSCy Schubert
2162b15cb3dSCy Schubert        # Adding
2172b15cb3dSCy Schubert        for entry in self._entries:
2182b15cb3dSCy Schubert            if entry.Array():
219*a466cc55SCy Schubert                self.PrintIndented(filep, "", entry.CodeAdd())
220*a466cc55SCy Schubert            filep.write("\n")
2212b15cb3dSCy Schubert
2222b15cb3dSCy Schubert        # Assigning
2232b15cb3dSCy Schubert        for entry in self._entries:
224*a466cc55SCy Schubert            self.PrintIndented(filep, "", entry.CodeAssign())
225*a466cc55SCy Schubert            filep.write("\n")
2262b15cb3dSCy Schubert
2272b15cb3dSCy Schubert        # Getting
2282b15cb3dSCy Schubert        for entry in self._entries:
229*a466cc55SCy Schubert            self.PrintIndented(filep, "", entry.CodeGet())
230*a466cc55SCy Schubert            filep.write("\n")
2312b15cb3dSCy Schubert
2322b15cb3dSCy Schubert        # Clearing
233*a466cc55SCy Schubert        filep.write(
234*a466cc55SCy Schubert            """void
235*a466cc55SCy Schubert%(name)s_clear(struct %(name)s *tmp)
236*a466cc55SCy Schubert{
237*a466cc55SCy Schubert"""
238*a466cc55SCy Schubert            % {"name": self._name}
239*a466cc55SCy Schubert        )
2402b15cb3dSCy Schubert        for entry in self._entries:
241*a466cc55SCy Schubert            self.PrintIndented(filep, "  ", entry.CodeClear("tmp"))
2422b15cb3dSCy Schubert
243*a466cc55SCy Schubert        filep.write("}\n\n")
2442b15cb3dSCy Schubert
2452b15cb3dSCy Schubert        # Freeing
246*a466cc55SCy Schubert        filep.write(
247*a466cc55SCy Schubert            """void
248*a466cc55SCy Schubert%(name)s_free(struct %(name)s *tmp)
249*a466cc55SCy Schubert{
250*a466cc55SCy Schubert"""
251*a466cc55SCy Schubert            % {"name": self._name}
252*a466cc55SCy Schubert        )
2532b15cb3dSCy Schubert
2542b15cb3dSCy Schubert        for entry in self._entries:
255*a466cc55SCy Schubert            self.PrintIndented(filep, "  ", entry.CodeFree("tmp"))
2562b15cb3dSCy Schubert
257*a466cc55SCy Schubert        filep.write(
258*a466cc55SCy Schubert            """  free(tmp);
259*a466cc55SCy Schubert}
260*a466cc55SCy Schubert
261*a466cc55SCy Schubert"""
262*a466cc55SCy Schubert        )
2632b15cb3dSCy Schubert
2642b15cb3dSCy Schubert        # Marshaling
265*a466cc55SCy Schubert        filep.write(
266*a466cc55SCy Schubert            """void
267*a466cc55SCy Schubert%(name)s_marshal(struct evbuffer *evbuf, const struct %(name)s *tmp) {
268*a466cc55SCy Schubert"""
269*a466cc55SCy Schubert            % {"name": self._name}
270*a466cc55SCy Schubert        )
2712b15cb3dSCy Schubert        for entry in self._entries:
272*a466cc55SCy Schubert            indent = "  "
2732b15cb3dSCy Schubert            # Optional entries do not have to be set
2742b15cb3dSCy Schubert            if entry.Optional():
275*a466cc55SCy Schubert                indent += "  "
276*a466cc55SCy Schubert                filep.write("  if (tmp->%s_set) {\n" % entry.Name())
2772b15cb3dSCy Schubert            self.PrintIndented(
278*a466cc55SCy Schubert                filep,
279*a466cc55SCy Schubert                indent,
280*a466cc55SCy Schubert                entry.CodeMarshal(
281*a466cc55SCy Schubert                    "evbuf",
282*a466cc55SCy Schubert                    self.EntryTagName(entry),
283*a466cc55SCy Schubert                    entry.GetVarName("tmp"),
284*a466cc55SCy Schubert                    entry.GetVarLen("tmp"),
285*a466cc55SCy Schubert                ),
286*a466cc55SCy Schubert            )
2872b15cb3dSCy Schubert            if entry.Optional():
288*a466cc55SCy Schubert                filep.write("  }\n")
2892b15cb3dSCy Schubert
290*a466cc55SCy Schubert        filep.write("}\n\n")
2912b15cb3dSCy Schubert
2922b15cb3dSCy Schubert        # Unmarshaling
293*a466cc55SCy Schubert        filep.write(
294*a466cc55SCy Schubert            """int
295*a466cc55SCy Schubert%(name)s_unmarshal(struct %(name)s *tmp, struct evbuffer *evbuf)
296*a466cc55SCy Schubert{
297*a466cc55SCy Schubert  ev_uint32_t tag;
298*a466cc55SCy Schubert  while (evbuffer_get_length(evbuf) > 0) {
299*a466cc55SCy Schubert    if (evtag_peek(evbuf, &tag) == -1)
300*a466cc55SCy Schubert      return (-1);
301*a466cc55SCy Schubert    switch (tag) {
302*a466cc55SCy Schubert
303*a466cc55SCy Schubert"""
304*a466cc55SCy Schubert            % {"name": self._name}
305*a466cc55SCy Schubert        )
3062b15cb3dSCy Schubert        for entry in self._entries:
307*a466cc55SCy Schubert            filep.write("      case %s:\n" % (self.EntryTagName(entry)))
3082b15cb3dSCy Schubert            if not entry.Array():
309*a466cc55SCy Schubert                filep.write(
310*a466cc55SCy Schubert                    """        if (tmp->%s_set)
311*a466cc55SCy Schubert          return (-1);
312*a466cc55SCy Schubert"""
313*a466cc55SCy Schubert                    % (entry.Name())
314*a466cc55SCy Schubert                )
3152b15cb3dSCy Schubert
3162b15cb3dSCy Schubert            self.PrintIndented(
317*a466cc55SCy Schubert                filep,
318*a466cc55SCy Schubert                "        ",
319*a466cc55SCy Schubert                entry.CodeUnmarshal(
320*a466cc55SCy Schubert                    "evbuf",
3212b15cb3dSCy Schubert                    self.EntryTagName(entry),
322*a466cc55SCy Schubert                    entry.GetVarName("tmp"),
323*a466cc55SCy Schubert                    entry.GetVarLen("tmp"),
324*a466cc55SCy Schubert                ),
325*a466cc55SCy Schubert            )
3262b15cb3dSCy Schubert
327*a466cc55SCy Schubert            filep.write(
328*a466cc55SCy Schubert                """        tmp->%s_set = 1;
329*a466cc55SCy Schubert        break;
330*a466cc55SCy Schubert"""
331*a466cc55SCy Schubert                % (entry.Name())
332*a466cc55SCy Schubert            )
333*a466cc55SCy Schubert        filep.write(
334*a466cc55SCy Schubert            """      default:
335*a466cc55SCy Schubert        return -1;
336*a466cc55SCy Schubert    }
337*a466cc55SCy Schubert  }
338*a466cc55SCy Schubert
339*a466cc55SCy Schubert"""
340*a466cc55SCy Schubert        )
3412b15cb3dSCy Schubert        # Check if it was decoded completely
342*a466cc55SCy Schubert        filep.write(
343*a466cc55SCy Schubert            """  if (%(name)s_complete(tmp) == -1)
344*a466cc55SCy Schubert    return (-1);
345*a466cc55SCy Schubert  return (0);
346*a466cc55SCy Schubert}
347*a466cc55SCy Schubert"""
348*a466cc55SCy Schubert            % {"name": self._name}
349*a466cc55SCy Schubert        )
3502b15cb3dSCy Schubert
3512b15cb3dSCy Schubert        # Checking if a structure has all the required data
352*a466cc55SCy Schubert        filep.write(
353*a466cc55SCy Schubert            """
354*a466cc55SCy Schubertint
355*a466cc55SCy Schubert%(name)s_complete(struct %(name)s *msg)
356*a466cc55SCy Schubert{
357*a466cc55SCy Schubert"""
358*a466cc55SCy Schubert            % {"name": self._name}
359*a466cc55SCy Schubert        )
3602b15cb3dSCy Schubert        for entry in self._entries:
3612b15cb3dSCy Schubert            if not entry.Optional():
3622b15cb3dSCy Schubert                code = [
363*a466cc55SCy Schubert                    """if (!msg->%(name)s_set)
364*a466cc55SCy Schubert    return (-1);"""
365*a466cc55SCy Schubert                ]
3662b15cb3dSCy Schubert                code = TranslateList(code, entry.GetTranslation())
367*a466cc55SCy Schubert                self.PrintIndented(filep, "  ", code)
3682b15cb3dSCy Schubert
3692b15cb3dSCy Schubert            self.PrintIndented(
370*a466cc55SCy Schubert                filep, "  ", entry.CodeComplete("msg", entry.GetVarName("msg"))
371*a466cc55SCy Schubert            )
372*a466cc55SCy Schubert        filep.write(
373*a466cc55SCy Schubert            """  return (0);
374*a466cc55SCy Schubert}
375*a466cc55SCy Schubert"""
376*a466cc55SCy Schubert        )
3772b15cb3dSCy Schubert
3782b15cb3dSCy Schubert        # Complete message unmarshaling
379*a466cc55SCy Schubert        filep.write(
380*a466cc55SCy Schubert            """
381*a466cc55SCy Schubertint
382*a466cc55SCy Schubertevtag_unmarshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t need_tag,
383*a466cc55SCy Schubert  struct %(name)s *msg)
384*a466cc55SCy Schubert{
385*a466cc55SCy Schubert  ev_uint32_t tag;
386*a466cc55SCy Schubert  int res = -1;
387*a466cc55SCy Schubert
388*a466cc55SCy Schubert  struct evbuffer *tmp = evbuffer_new();
389*a466cc55SCy Schubert
390*a466cc55SCy Schubert  if (evtag_unmarshal(evbuf, &tag, tmp) == -1 || tag != need_tag)
391*a466cc55SCy Schubert    goto error;
392*a466cc55SCy Schubert
393*a466cc55SCy Schubert  if (%(name)s_unmarshal(msg, tmp) == -1)
394*a466cc55SCy Schubert    goto error;
395*a466cc55SCy Schubert
396*a466cc55SCy Schubert  res = 0;
397*a466cc55SCy Schubert
398*a466cc55SCy Schubert error:
399*a466cc55SCy Schubert  evbuffer_free(tmp);
400*a466cc55SCy Schubert  return (res);
401*a466cc55SCy Schubert}
402*a466cc55SCy Schubert"""
403*a466cc55SCy Schubert            % {"name": self._name}
404*a466cc55SCy Schubert        )
4052b15cb3dSCy Schubert
4062b15cb3dSCy Schubert        # Complete message marshaling
407*a466cc55SCy Schubert        filep.write(
408*a466cc55SCy Schubert            """
409*a466cc55SCy Schubertvoid
410*a466cc55SCy Schubertevtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag,
411*a466cc55SCy Schubert    const struct %(name)s *msg)
412*a466cc55SCy Schubert{
413*a466cc55SCy Schubert  struct evbuffer *buf_ = evbuffer_new();
414*a466cc55SCy Schubert  assert(buf_ != NULL);
415*a466cc55SCy Schubert  %(name)s_marshal(buf_, msg);
416*a466cc55SCy Schubert  evtag_marshal_buffer(evbuf, tag, buf_);
417*a466cc55SCy Schubert  evbuffer_free(buf_);
418*a466cc55SCy Schubert}
4192b15cb3dSCy Schubert
420*a466cc55SCy Schubert"""
421*a466cc55SCy Schubert            % {"name": self._name}
422*a466cc55SCy Schubert        )
423*a466cc55SCy Schubert
424*a466cc55SCy Schubert
425*a466cc55SCy Schubertclass Entry(object):
426*a466cc55SCy Schubert    def __init__(self, ent_type, name, tag):
427*a466cc55SCy Schubert        self._type = ent_type
4282b15cb3dSCy Schubert        self._name = name
4292b15cb3dSCy Schubert        self._tag = int(tag)
430*a466cc55SCy Schubert        self._ctype = ent_type
431*a466cc55SCy Schubert        self._optional = False
432*a466cc55SCy Schubert        self._can_be_array = False
433*a466cc55SCy Schubert        self._array = False
4342b15cb3dSCy Schubert        self._line_count = -1
4352b15cb3dSCy Schubert        self._struct = None
4362b15cb3dSCy Schubert        self._refname = None
4372b15cb3dSCy Schubert
4382b15cb3dSCy Schubert        self._optpointer = True
4392b15cb3dSCy Schubert        self._optaddarg = True
4402b15cb3dSCy Schubert
441*a466cc55SCy Schubert    @staticmethod
442*a466cc55SCy Schubert    def GetInitializer():
443*a466cc55SCy Schubert        raise NotImplementedError("Entry does not provide an initializer")
4442b15cb3dSCy Schubert
4452b15cb3dSCy Schubert    def SetStruct(self, struct):
4462b15cb3dSCy Schubert        self._struct = struct
4472b15cb3dSCy Schubert
4482b15cb3dSCy Schubert    def LineCount(self):
4492b15cb3dSCy Schubert        assert self._line_count != -1
4502b15cb3dSCy Schubert        return self._line_count
4512b15cb3dSCy Schubert
4522b15cb3dSCy Schubert    def SetLineCount(self, number):
4532b15cb3dSCy Schubert        self._line_count = number
4542b15cb3dSCy Schubert
4552b15cb3dSCy Schubert    def Array(self):
4562b15cb3dSCy Schubert        return self._array
4572b15cb3dSCy Schubert
4582b15cb3dSCy Schubert    def Optional(self):
4592b15cb3dSCy Schubert        return self._optional
4602b15cb3dSCy Schubert
4612b15cb3dSCy Schubert    def Tag(self):
4622b15cb3dSCy Schubert        return self._tag
4632b15cb3dSCy Schubert
4642b15cb3dSCy Schubert    def Name(self):
4652b15cb3dSCy Schubert        return self._name
4662b15cb3dSCy Schubert
4672b15cb3dSCy Schubert    def Type(self):
4682b15cb3dSCy Schubert        return self._type
4692b15cb3dSCy Schubert
470*a466cc55SCy Schubert    def MakeArray(self):
471*a466cc55SCy Schubert        self._array = True
4722b15cb3dSCy Schubert
4732b15cb3dSCy Schubert    def MakeOptional(self):
474*a466cc55SCy Schubert        self._optional = True
4752b15cb3dSCy Schubert
4762b15cb3dSCy Schubert    def Verify(self):
4772b15cb3dSCy Schubert        if self.Array() and not self._can_be_array:
4782b15cb3dSCy Schubert            raise RpcGenError(
4792b15cb3dSCy Schubert                'Entry "%s" cannot be created as an array '
480*a466cc55SCy Schubert                "around line %d" % (self._name, self.LineCount())
481*a466cc55SCy Schubert            )
4822b15cb3dSCy Schubert        if not self._struct:
4832b15cb3dSCy Schubert            raise RpcGenError(
4842b15cb3dSCy Schubert                'Entry "%s" does not know which struct it belongs to '
485*a466cc55SCy Schubert                "around line %d" % (self._name, self.LineCount())
486*a466cc55SCy Schubert            )
4872b15cb3dSCy Schubert        if self._optional and self._array:
4882b15cb3dSCy Schubert            raise RpcGenError(
4892b15cb3dSCy Schubert                'Entry "%s" has illegal combination of optional and array '
490*a466cc55SCy Schubert                "around line %d" % (self._name, self.LineCount())
491*a466cc55SCy Schubert            )
4922b15cb3dSCy Schubert
493*a466cc55SCy Schubert    def GetTranslation(self, extradict=None):
494*a466cc55SCy Schubert        if extradict is None:
495*a466cc55SCy Schubert            extradict = {}
4962b15cb3dSCy Schubert        mapping = {
4972b15cb3dSCy Schubert            "parent_name": self._struct.Name(),
4982b15cb3dSCy Schubert            "name": self._name,
4992b15cb3dSCy Schubert            "ctype": self._ctype,
5002b15cb3dSCy Schubert            "refname": self._refname,
5012b15cb3dSCy Schubert            "optpointer": self._optpointer and "*" or "",
5022b15cb3dSCy Schubert            "optreference": self._optpointer and "&" or "",
503*a466cc55SCy Schubert            "optaddarg": self._optaddarg and ", const %s value" % self._ctype or "",
5042b15cb3dSCy Schubert        }
505*a466cc55SCy Schubert        for (k, v) in list(extradict.items()):
5062b15cb3dSCy Schubert            mapping[k] = v
5072b15cb3dSCy Schubert
5082b15cb3dSCy Schubert        return mapping
5092b15cb3dSCy Schubert
5102b15cb3dSCy Schubert    def GetVarName(self, var):
511*a466cc55SCy Schubert        return "%(var)s->%(name)s_data" % self.GetTranslation({"var": var})
5122b15cb3dSCy Schubert
513*a466cc55SCy Schubert    def GetVarLen(self, _var):
514*a466cc55SCy Schubert        return "sizeof(%s)" % self._ctype
5152b15cb3dSCy Schubert
5162b15cb3dSCy Schubert    def GetFuncName(self):
517*a466cc55SCy Schubert        return "%s_%s_get" % (self._struct.Name(), self._name)
5182b15cb3dSCy Schubert
5192b15cb3dSCy Schubert    def GetDeclaration(self, funcname):
520*a466cc55SCy Schubert        code = [
521*a466cc55SCy Schubert            "int %s(struct %s *, %s *);" % (funcname, self._struct.Name(), self._ctype)
522*a466cc55SCy Schubert        ]
5232b15cb3dSCy Schubert        return code
5242b15cb3dSCy Schubert
5252b15cb3dSCy Schubert    def CodeGet(self):
526*a466cc55SCy Schubert        code = """int
527*a466cc55SCy Schubert%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, %(ctype)s *value)
528*a466cc55SCy Schubert{
529*a466cc55SCy Schubert  if (msg->%(name)s_set != 1)
530*a466cc55SCy Schubert    return (-1);
531*a466cc55SCy Schubert  *value = msg->%(name)s_data;
532*a466cc55SCy Schubert  return (0);
533*a466cc55SCy Schubert}"""
5342b15cb3dSCy Schubert        code = code % self.GetTranslation()
535*a466cc55SCy Schubert        return code.split("\n")
5362b15cb3dSCy Schubert
5372b15cb3dSCy Schubert    def AssignFuncName(self):
538*a466cc55SCy Schubert        return "%s_%s_assign" % (self._struct.Name(), self._name)
5392b15cb3dSCy Schubert
5402b15cb3dSCy Schubert    def AddFuncName(self):
541*a466cc55SCy Schubert        return "%s_%s_add" % (self._struct.Name(), self._name)
5422b15cb3dSCy Schubert
5432b15cb3dSCy Schubert    def AssignDeclaration(self, funcname):
544*a466cc55SCy Schubert        code = [
545*a466cc55SCy Schubert            "int %s(struct %s *, const %s);"
546*a466cc55SCy Schubert            % (funcname, self._struct.Name(), self._ctype)
547*a466cc55SCy Schubert        ]
5482b15cb3dSCy Schubert        return code
5492b15cb3dSCy Schubert
5502b15cb3dSCy Schubert    def CodeAssign(self):
551*a466cc55SCy Schubert        code = [
552*a466cc55SCy Schubert            "int",
553*a466cc55SCy Schubert            "%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,"
554*a466cc55SCy Schubert            " const %(ctype)s value)",
555*a466cc55SCy Schubert            "{",
556*a466cc55SCy Schubert            "  msg->%(name)s_set = 1;",
557*a466cc55SCy Schubert            "  msg->%(name)s_data = value;",
558*a466cc55SCy Schubert            "  return (0);",
559*a466cc55SCy Schubert            "}",
560*a466cc55SCy Schubert        ]
561*a466cc55SCy Schubert        code = "\n".join(code)
5622b15cb3dSCy Schubert        code = code % self.GetTranslation()
563*a466cc55SCy Schubert        return code.split("\n")
5642b15cb3dSCy Schubert
5652b15cb3dSCy Schubert    def CodeClear(self, structname):
566*a466cc55SCy Schubert        code = ["%s->%s_set = 0;" % (structname, self.Name())]
5672b15cb3dSCy Schubert
5682b15cb3dSCy Schubert        return code
5692b15cb3dSCy Schubert
570*a466cc55SCy Schubert    @staticmethod
571*a466cc55SCy Schubert    def CodeComplete(_structname, _var_name):
5722b15cb3dSCy Schubert        return []
5732b15cb3dSCy Schubert
574*a466cc55SCy Schubert    @staticmethod
575*a466cc55SCy Schubert    def CodeFree(_name):
5762b15cb3dSCy Schubert        return []
5772b15cb3dSCy Schubert
5782b15cb3dSCy Schubert    def CodeBase(self):
579*a466cc55SCy Schubert        code = ["%(parent_name)s_%(name)s_assign,", "%(parent_name)s_%(name)s_get,"]
5802b15cb3dSCy Schubert        if self.Array():
581*a466cc55SCy Schubert            code.append("%(parent_name)s_%(name)s_add,")
5822b15cb3dSCy Schubert
583*a466cc55SCy Schubert        code = "\n".join(code)
5842b15cb3dSCy Schubert        code = code % self.GetTranslation()
585*a466cc55SCy Schubert        return code.split("\n")
586*a466cc55SCy Schubert
5872b15cb3dSCy Schubert
5882b15cb3dSCy Schubertclass EntryBytes(Entry):
589*a466cc55SCy Schubert    def __init__(self, ent_type, name, tag, length):
5902b15cb3dSCy Schubert        # Init base class
591*a466cc55SCy Schubert        super(EntryBytes, self).__init__(ent_type, name, tag)
5922b15cb3dSCy Schubert
5932b15cb3dSCy Schubert        self._length = length
594*a466cc55SCy Schubert        self._ctype = "ev_uint8_t"
5952b15cb3dSCy Schubert
596*a466cc55SCy Schubert    @staticmethod
597*a466cc55SCy Schubert    def GetInitializer():
5982b15cb3dSCy Schubert        return "NULL"
5992b15cb3dSCy Schubert
600*a466cc55SCy Schubert    def GetVarLen(self, _var):
601*a466cc55SCy Schubert        return "(%s)" % self._length
6022b15cb3dSCy Schubert
603*a466cc55SCy Schubert    @staticmethod
604*a466cc55SCy Schubert    def CodeArrayAdd(varname, _value):
6052b15cb3dSCy Schubert        # XXX: copy here
606*a466cc55SCy Schubert        return ["%(varname)s = NULL;" % {"varname": varname}]
6072b15cb3dSCy Schubert
6082b15cb3dSCy Schubert    def GetDeclaration(self, funcname):
609*a466cc55SCy Schubert        code = [
610*a466cc55SCy Schubert            "int %s(struct %s *, %s **);" % (funcname, self._struct.Name(), self._ctype)
611*a466cc55SCy Schubert        ]
6122b15cb3dSCy Schubert        return code
6132b15cb3dSCy Schubert
6142b15cb3dSCy Schubert    def AssignDeclaration(self, funcname):
615*a466cc55SCy Schubert        code = [
616*a466cc55SCy Schubert            "int %s(struct %s *, const %s *);"
617*a466cc55SCy Schubert            % (funcname, self._struct.Name(), self._ctype)
618*a466cc55SCy Schubert        ]
6192b15cb3dSCy Schubert        return code
6202b15cb3dSCy Schubert
6212b15cb3dSCy Schubert    def Declaration(self):
622*a466cc55SCy Schubert        dcl = ["ev_uint8_t %s_data[%s];" % (self._name, self._length)]
6232b15cb3dSCy Schubert
6242b15cb3dSCy Schubert        return dcl
6252b15cb3dSCy Schubert
6262b15cb3dSCy Schubert    def CodeGet(self):
6272b15cb3dSCy Schubert        name = self._name
628*a466cc55SCy Schubert        code = [
629*a466cc55SCy Schubert            "int",
630*a466cc55SCy Schubert            "%s_%s_get(struct %s *msg, %s **value)"
631*a466cc55SCy Schubert            % (self._struct.Name(), name, self._struct.Name(), self._ctype),
632*a466cc55SCy Schubert            "{",
633*a466cc55SCy Schubert            "  if (msg->%s_set != 1)" % name,
634*a466cc55SCy Schubert            "    return (-1);",
635*a466cc55SCy Schubert            "  *value = msg->%s_data;" % name,
636*a466cc55SCy Schubert            "  return (0);",
637*a466cc55SCy Schubert            "}",
638*a466cc55SCy Schubert        ]
6392b15cb3dSCy Schubert        return code
6402b15cb3dSCy Schubert
6412b15cb3dSCy Schubert    def CodeAssign(self):
6422b15cb3dSCy Schubert        name = self._name
643*a466cc55SCy Schubert        code = [
644*a466cc55SCy Schubert            "int",
645*a466cc55SCy Schubert            "%s_%s_assign(struct %s *msg, const %s *value)"
646*a466cc55SCy Schubert            % (self._struct.Name(), name, self._struct.Name(), self._ctype),
647*a466cc55SCy Schubert            "{",
648*a466cc55SCy Schubert            "  msg->%s_set = 1;" % name,
649*a466cc55SCy Schubert            "  memcpy(msg->%s_data, value, %s);" % (name, self._length),
650*a466cc55SCy Schubert            "  return (0);",
651*a466cc55SCy Schubert            "}",
652*a466cc55SCy Schubert        ]
6532b15cb3dSCy Schubert        return code
6542b15cb3dSCy Schubert
6552b15cb3dSCy Schubert    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
656*a466cc55SCy Schubert        code = [
657*a466cc55SCy Schubert            "if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, "
658*a466cc55SCy Schubert            "%(var)s, %(varlen)s) == -1) {",
6592b15cb3dSCy Schubert            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
660*a466cc55SCy Schubert            "  return (-1);",
661*a466cc55SCy Schubert            "}",
6622b15cb3dSCy Schubert        ]
663*a466cc55SCy Schubert        return TranslateList(
664*a466cc55SCy Schubert            code,
665*a466cc55SCy Schubert            self.GetTranslation(
666*a466cc55SCy Schubert                {"var": var_name, "varlen": var_len, "buf": buf, "tag": tag_name}
667*a466cc55SCy Schubert            ),
668*a466cc55SCy Schubert        )
6692b15cb3dSCy Schubert
670*a466cc55SCy Schubert    @staticmethod
671*a466cc55SCy Schubert    def CodeMarshal(buf, tag_name, var_name, var_len):
672*a466cc55SCy Schubert        code = ["evtag_marshal(%s, %s, %s, %s);" % (buf, tag_name, var_name, var_len)]
6732b15cb3dSCy Schubert        return code
6742b15cb3dSCy Schubert
6752b15cb3dSCy Schubert    def CodeClear(self, structname):
676*a466cc55SCy Schubert        code = [
677*a466cc55SCy Schubert            "%s->%s_set = 0;" % (structname, self.Name()),
678*a466cc55SCy Schubert            "memset(%s->%s_data, 0, sizeof(%s->%s_data));"
679*a466cc55SCy Schubert            % (structname, self._name, structname, self._name),
680*a466cc55SCy Schubert        ]
6812b15cb3dSCy Schubert
6822b15cb3dSCy Schubert        return code
6832b15cb3dSCy Schubert
6842b15cb3dSCy Schubert    def CodeInitialize(self, name):
685*a466cc55SCy Schubert        code = [
686*a466cc55SCy Schubert            "memset(%s->%s_data, 0, sizeof(%s->%s_data));"
687*a466cc55SCy Schubert            % (name, self._name, name, self._name)
688*a466cc55SCy Schubert        ]
6892b15cb3dSCy Schubert        return code
6902b15cb3dSCy Schubert
6912b15cb3dSCy Schubert    def Verify(self):
6922b15cb3dSCy Schubert        if not self._length:
6932b15cb3dSCy Schubert            raise RpcGenError(
6942b15cb3dSCy Schubert                'Entry "%s" needs a length '
695*a466cc55SCy Schubert                "around line %d" % (self._name, self.LineCount())
696*a466cc55SCy Schubert            )
6972b15cb3dSCy Schubert
698*a466cc55SCy Schubert        super(EntryBytes, self).Verify()
699*a466cc55SCy Schubert
7002b15cb3dSCy Schubert
7012b15cb3dSCy Schubertclass EntryInt(Entry):
702*a466cc55SCy Schubert    def __init__(self, ent_type, name, tag, bits=32):
7032b15cb3dSCy Schubert        # Init base class
704*a466cc55SCy Schubert        super(EntryInt, self).__init__(ent_type, name, tag)
7052b15cb3dSCy Schubert
706*a466cc55SCy Schubert        self._can_be_array = True
7072b15cb3dSCy Schubert        if bits == 32:
708*a466cc55SCy Schubert            self._ctype = "ev_uint32_t"
709*a466cc55SCy Schubert            self._marshal_type = "int"
7102b15cb3dSCy Schubert        if bits == 64:
711*a466cc55SCy Schubert            self._ctype = "ev_uint64_t"
712*a466cc55SCy Schubert            self._marshal_type = "int64"
7132b15cb3dSCy Schubert
714*a466cc55SCy Schubert    @staticmethod
715*a466cc55SCy Schubert    def GetInitializer():
7162b15cb3dSCy Schubert        return "0"
7172b15cb3dSCy Schubert
718*a466cc55SCy Schubert    @staticmethod
719*a466cc55SCy Schubert    def CodeArrayFree(_var):
7202b15cb3dSCy Schubert        return []
7212b15cb3dSCy Schubert
722*a466cc55SCy Schubert    @staticmethod
723*a466cc55SCy Schubert    def CodeArrayAssign(varname, srcvar):
724*a466cc55SCy Schubert        return ["%(varname)s = %(srcvar)s;" % {"varname": varname, "srcvar": srcvar}]
7252b15cb3dSCy Schubert
726*a466cc55SCy Schubert    @staticmethod
727*a466cc55SCy Schubert    def CodeArrayAdd(varname, value):
7282b15cb3dSCy Schubert        """Returns a new entry of this type."""
729*a466cc55SCy Schubert        return ["%(varname)s = %(value)s;" % {"varname": varname, "value": value}]
7302b15cb3dSCy Schubert
731*a466cc55SCy Schubert    def CodeUnmarshal(self, buf, tag_name, var_name, _var_len):
7322b15cb3dSCy Schubert        code = [
733*a466cc55SCy Schubert            "if (evtag_unmarshal_%(ma)s(%(buf)s, %(tag)s, &%(var)s) == -1) {",
7342b15cb3dSCy Schubert            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
735*a466cc55SCy Schubert            "  return (-1);",
736*a466cc55SCy Schubert            "}",
737*a466cc55SCy Schubert        ]
738*a466cc55SCy Schubert        code = "\n".join(code) % self.GetTranslation(
739*a466cc55SCy Schubert            {"ma": self._marshal_type, "buf": buf, "tag": tag_name, "var": var_name}
740*a466cc55SCy Schubert        )
741*a466cc55SCy Schubert        return code.split("\n")
7422b15cb3dSCy Schubert
743*a466cc55SCy Schubert    def CodeMarshal(self, buf, tag_name, var_name, _var_len):
7442b15cb3dSCy Schubert        code = [
745*a466cc55SCy Schubert            "evtag_marshal_%s(%s, %s, %s);"
746*a466cc55SCy Schubert            % (self._marshal_type, buf, tag_name, var_name)
747*a466cc55SCy Schubert        ]
7482b15cb3dSCy Schubert        return code
7492b15cb3dSCy Schubert
7502b15cb3dSCy Schubert    def Declaration(self):
751*a466cc55SCy Schubert        dcl = ["%s %s_data;" % (self._ctype, self._name)]
7522b15cb3dSCy Schubert
7532b15cb3dSCy Schubert        return dcl
7542b15cb3dSCy Schubert
7552b15cb3dSCy Schubert    def CodeInitialize(self, name):
756*a466cc55SCy Schubert        code = ["%s->%s_data = 0;" % (name, self._name)]
7572b15cb3dSCy Schubert        return code
7582b15cb3dSCy Schubert
759*a466cc55SCy Schubert
7602b15cb3dSCy Schubertclass EntryString(Entry):
761*a466cc55SCy Schubert    def __init__(self, ent_type, name, tag):
7622b15cb3dSCy Schubert        # Init base class
763*a466cc55SCy Schubert        super(EntryString, self).__init__(ent_type, name, tag)
7642b15cb3dSCy Schubert
765*a466cc55SCy Schubert        self._can_be_array = True
766*a466cc55SCy Schubert        self._ctype = "char *"
7672b15cb3dSCy Schubert
768*a466cc55SCy Schubert    @staticmethod
769*a466cc55SCy Schubert    def GetInitializer():
7702b15cb3dSCy Schubert        return "NULL"
7712b15cb3dSCy Schubert
772*a466cc55SCy Schubert    @staticmethod
773*a466cc55SCy Schubert    def CodeArrayFree(varname):
774*a466cc55SCy Schubert        code = ["if (%(var)s != NULL) free(%(var)s);"]
7752b15cb3dSCy Schubert
776*a466cc55SCy Schubert        return TranslateList(code, {"var": varname})
7772b15cb3dSCy Schubert
778*a466cc55SCy Schubert    @staticmethod
779*a466cc55SCy Schubert    def CodeArrayAssign(varname, srcvar):
7802b15cb3dSCy Schubert        code = [
781*a466cc55SCy Schubert            "if (%(var)s != NULL)",
782*a466cc55SCy Schubert            "  free(%(var)s);",
783*a466cc55SCy Schubert            "%(var)s = strdup(%(srcvar)s);",
784*a466cc55SCy Schubert            "if (%(var)s == NULL) {",
7852b15cb3dSCy Schubert            '  event_warnx("%%s: strdup", __func__);',
786*a466cc55SCy Schubert            "  return (-1);",
787*a466cc55SCy Schubert            "}",
788*a466cc55SCy Schubert        ]
7892b15cb3dSCy Schubert
790*a466cc55SCy Schubert        return TranslateList(code, {"var": varname, "srcvar": srcvar})
7912b15cb3dSCy Schubert
792*a466cc55SCy Schubert    @staticmethod
793*a466cc55SCy Schubert    def CodeArrayAdd(varname, value):
7942b15cb3dSCy Schubert        code = [
795*a466cc55SCy Schubert            "if (%(value)s != NULL) {",
796*a466cc55SCy Schubert            "  %(var)s = strdup(%(value)s);",
797*a466cc55SCy Schubert            "  if (%(var)s == NULL) {",
798*a466cc55SCy Schubert            "    goto error;",
799*a466cc55SCy Schubert            "  }",
800*a466cc55SCy Schubert            "} else {",
801*a466cc55SCy Schubert            "  %(var)s = NULL;",
802*a466cc55SCy Schubert            "}",
803*a466cc55SCy Schubert        ]
8042b15cb3dSCy Schubert
805*a466cc55SCy Schubert        return TranslateList(code, {"var": varname, "value": value})
8062b15cb3dSCy Schubert
8072b15cb3dSCy Schubert    def GetVarLen(self, var):
808*a466cc55SCy Schubert        return "strlen(%s)" % self.GetVarName(var)
8092b15cb3dSCy Schubert
810*a466cc55SCy Schubert    @staticmethod
811*a466cc55SCy Schubert    def CodeMakeInitalize(varname):
812*a466cc55SCy Schubert        return "%(varname)s = NULL;" % {"varname": varname}
8132b15cb3dSCy Schubert
8142b15cb3dSCy Schubert    def CodeAssign(self):
8152b15cb3dSCy Schubert        code = """int
8162b15cb3dSCy Schubert%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
8172b15cb3dSCy Schubert    const %(ctype)s value)
8182b15cb3dSCy Schubert{
8192b15cb3dSCy Schubert  if (msg->%(name)s_data != NULL)
8202b15cb3dSCy Schubert    free(msg->%(name)s_data);
8212b15cb3dSCy Schubert  if ((msg->%(name)s_data = strdup(value)) == NULL)
8222b15cb3dSCy Schubert    return (-1);
8232b15cb3dSCy Schubert  msg->%(name)s_set = 1;
8242b15cb3dSCy Schubert  return (0);
825*a466cc55SCy Schubert}""" % (
826*a466cc55SCy Schubert            self.GetTranslation()
827*a466cc55SCy Schubert        )
8282b15cb3dSCy Schubert
829*a466cc55SCy Schubert        return code.split("\n")
8302b15cb3dSCy Schubert
831*a466cc55SCy Schubert    def CodeUnmarshal(self, buf, tag_name, var_name, _var_len):
832*a466cc55SCy Schubert        code = [
833*a466cc55SCy Schubert            "if (evtag_unmarshal_string(%(buf)s, %(tag)s, &%(var)s) == -1) {",
8342b15cb3dSCy Schubert            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
835*a466cc55SCy Schubert            "  return (-1);",
836*a466cc55SCy Schubert            "}",
8372b15cb3dSCy Schubert        ]
838*a466cc55SCy Schubert        code = "\n".join(code) % self.GetTranslation(
839*a466cc55SCy Schubert            {"buf": buf, "tag": tag_name, "var": var_name}
840*a466cc55SCy Schubert        )
841*a466cc55SCy Schubert        return code.split("\n")
8422b15cb3dSCy Schubert
843*a466cc55SCy Schubert    @staticmethod
844*a466cc55SCy Schubert    def CodeMarshal(buf, tag_name, var_name, _var_len):
845*a466cc55SCy Schubert        code = ["evtag_marshal_string(%s, %s, %s);" % (buf, tag_name, var_name)]
8462b15cb3dSCy Schubert        return code
8472b15cb3dSCy Schubert
8482b15cb3dSCy Schubert    def CodeClear(self, structname):
849*a466cc55SCy Schubert        code = [
850*a466cc55SCy Schubert            "if (%s->%s_set == 1) {" % (structname, self.Name()),
851*a466cc55SCy Schubert            "  free(%s->%s_data);" % (structname, self.Name()),
852*a466cc55SCy Schubert            "  %s->%s_data = NULL;" % (structname, self.Name()),
853*a466cc55SCy Schubert            "  %s->%s_set = 0;" % (structname, self.Name()),
854*a466cc55SCy Schubert            "}",
8552b15cb3dSCy Schubert        ]
8562b15cb3dSCy Schubert
8572b15cb3dSCy Schubert        return code
8582b15cb3dSCy Schubert
8592b15cb3dSCy Schubert    def CodeInitialize(self, name):
860*a466cc55SCy Schubert        code = ["%s->%s_data = NULL;" % (name, self._name)]
8612b15cb3dSCy Schubert        return code
8622b15cb3dSCy Schubert
8632b15cb3dSCy Schubert    def CodeFree(self, name):
864*a466cc55SCy Schubert        code = [
865*a466cc55SCy Schubert            "if (%s->%s_data != NULL)" % (name, self._name),
866*a466cc55SCy Schubert            "    free (%s->%s_data);" % (name, self._name),
867*a466cc55SCy Schubert        ]
8682b15cb3dSCy Schubert
8692b15cb3dSCy Schubert        return code
8702b15cb3dSCy Schubert
8712b15cb3dSCy Schubert    def Declaration(self):
872*a466cc55SCy Schubert        dcl = ["char *%s_data;" % self._name]
8732b15cb3dSCy Schubert
8742b15cb3dSCy Schubert        return dcl
8752b15cb3dSCy Schubert
876*a466cc55SCy Schubert
8772b15cb3dSCy Schubertclass EntryStruct(Entry):
878*a466cc55SCy Schubert    def __init__(self, ent_type, name, tag, refname):
8792b15cb3dSCy Schubert        # Init base class
880*a466cc55SCy Schubert        super(EntryStruct, self).__init__(ent_type, name, tag)
8812b15cb3dSCy Schubert
8822b15cb3dSCy Schubert        self._optpointer = False
883*a466cc55SCy Schubert        self._can_be_array = True
8842b15cb3dSCy Schubert        self._refname = refname
885*a466cc55SCy Schubert        self._ctype = "struct %s*" % refname
8862b15cb3dSCy Schubert        self._optaddarg = False
8872b15cb3dSCy Schubert
8882b15cb3dSCy Schubert    def GetInitializer(self):
8892b15cb3dSCy Schubert        return "NULL"
8902b15cb3dSCy Schubert
891*a466cc55SCy Schubert    def GetVarLen(self, _var):
892*a466cc55SCy Schubert        return "-1"
8932b15cb3dSCy Schubert
894*a466cc55SCy Schubert    def CodeArrayAdd(self, varname, _value):
8952b15cb3dSCy Schubert        code = [
896*a466cc55SCy Schubert            "%(varname)s = %(refname)s_new();",
897*a466cc55SCy Schubert            "if (%(varname)s == NULL)",
898*a466cc55SCy Schubert            "  goto error;",
899*a466cc55SCy Schubert        ]
9002b15cb3dSCy Schubert
901*a466cc55SCy Schubert        return TranslateList(code, self.GetTranslation({"varname": varname}))
9022b15cb3dSCy Schubert
9032b15cb3dSCy Schubert    def CodeArrayFree(self, var):
904*a466cc55SCy Schubert        code = ["%(refname)s_free(%(var)s);" % self.GetTranslation({"var": var})]
9052b15cb3dSCy Schubert        return code
9062b15cb3dSCy Schubert
9072b15cb3dSCy Schubert    def CodeArrayAssign(self, var, srcvar):
9082b15cb3dSCy Schubert        code = [
909*a466cc55SCy Schubert            "int had_error = 0;",
910*a466cc55SCy Schubert            "struct evbuffer *tmp = NULL;",
911*a466cc55SCy Schubert            "%(refname)s_clear(%(var)s);",
912*a466cc55SCy Schubert            "if ((tmp = evbuffer_new()) == NULL) {",
9132b15cb3dSCy Schubert            '  event_warn("%%s: evbuffer_new()", __func__);',
914*a466cc55SCy Schubert            "  had_error = 1;",
915*a466cc55SCy Schubert            "  goto done;",
916*a466cc55SCy Schubert            "}",
917*a466cc55SCy Schubert            "%(refname)s_marshal(tmp, %(srcvar)s);",
918*a466cc55SCy Schubert            "if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {",
9192b15cb3dSCy Schubert            '  event_warnx("%%s: %(refname)s_unmarshal", __func__);',
920*a466cc55SCy Schubert            "  had_error = 1;",
921*a466cc55SCy Schubert            "  goto done;",
922*a466cc55SCy Schubert            "}",
923*a466cc55SCy Schubert            "done:",
924*a466cc55SCy Schubert            "if (tmp != NULL)",
925*a466cc55SCy Schubert            "  evbuffer_free(tmp);",
926*a466cc55SCy Schubert            "if (had_error) {",
927*a466cc55SCy Schubert            "  %(refname)s_clear(%(var)s);",
928*a466cc55SCy Schubert            "  return (-1);",
929*a466cc55SCy Schubert            "}",
930*a466cc55SCy Schubert        ]
9312b15cb3dSCy Schubert
932*a466cc55SCy Schubert        return TranslateList(code, self.GetTranslation({"var": var, "srcvar": srcvar}))
9332b15cb3dSCy Schubert
9342b15cb3dSCy Schubert    def CodeGet(self):
9352b15cb3dSCy Schubert        name = self._name
936*a466cc55SCy Schubert        code = [
937*a466cc55SCy Schubert            "int",
938*a466cc55SCy Schubert            "%s_%s_get(struct %s *msg, %s *value)"
939*a466cc55SCy Schubert            % (self._struct.Name(), name, self._struct.Name(), self._ctype),
940*a466cc55SCy Schubert            "{",
941*a466cc55SCy Schubert            "  if (msg->%s_set != 1) {" % name,
942*a466cc55SCy Schubert            "    msg->%s_data = %s_new();" % (name, self._refname),
943*a466cc55SCy Schubert            "    if (msg->%s_data == NULL)" % name,
944*a466cc55SCy Schubert            "      return (-1);",
945*a466cc55SCy Schubert            "    msg->%s_set = 1;" % name,
946*a466cc55SCy Schubert            "  }",
947*a466cc55SCy Schubert            "  *value = msg->%s_data;" % name,
948*a466cc55SCy Schubert            "  return (0);",
949*a466cc55SCy Schubert            "}",
950*a466cc55SCy Schubert        ]
9512b15cb3dSCy Schubert        return code
9522b15cb3dSCy Schubert
9532b15cb3dSCy Schubert    def CodeAssign(self):
954*a466cc55SCy Schubert        code = (
955*a466cc55SCy Schubert            """int
9562b15cb3dSCy Schubert%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
9572b15cb3dSCy Schubert    const %(ctype)s value)
9582b15cb3dSCy Schubert{
9592b15cb3dSCy Schubert   struct evbuffer *tmp = NULL;
9602b15cb3dSCy Schubert   if (msg->%(name)s_set) {
9612b15cb3dSCy Schubert     %(refname)s_clear(msg->%(name)s_data);
9622b15cb3dSCy Schubert     msg->%(name)s_set = 0;
9632b15cb3dSCy Schubert   } else {
9642b15cb3dSCy Schubert     msg->%(name)s_data = %(refname)s_new();
9652b15cb3dSCy Schubert     if (msg->%(name)s_data == NULL) {
9662b15cb3dSCy Schubert       event_warn("%%s: %(refname)s_new()", __func__);
9672b15cb3dSCy Schubert       goto error;
9682b15cb3dSCy Schubert     }
9692b15cb3dSCy Schubert   }
9702b15cb3dSCy Schubert   if ((tmp = evbuffer_new()) == NULL) {
9712b15cb3dSCy Schubert     event_warn("%%s: evbuffer_new()", __func__);
9722b15cb3dSCy Schubert     goto error;
9732b15cb3dSCy Schubert   }
9742b15cb3dSCy Schubert   %(refname)s_marshal(tmp, value);
9752b15cb3dSCy Schubert   if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) {
9762b15cb3dSCy Schubert     event_warnx("%%s: %(refname)s_unmarshal", __func__);
9772b15cb3dSCy Schubert     goto error;
9782b15cb3dSCy Schubert   }
9792b15cb3dSCy Schubert   msg->%(name)s_set = 1;
9802b15cb3dSCy Schubert   evbuffer_free(tmp);
9812b15cb3dSCy Schubert   return (0);
9822b15cb3dSCy Schubert error:
9832b15cb3dSCy Schubert   if (tmp != NULL)
9842b15cb3dSCy Schubert     evbuffer_free(tmp);
9852b15cb3dSCy Schubert   if (msg->%(name)s_data != NULL) {
9862b15cb3dSCy Schubert     %(refname)s_free(msg->%(name)s_data);
9872b15cb3dSCy Schubert     msg->%(name)s_data = NULL;
9882b15cb3dSCy Schubert   }
9892b15cb3dSCy Schubert   return (-1);
990*a466cc55SCy Schubert}"""
991*a466cc55SCy Schubert            % self.GetTranslation()
992*a466cc55SCy Schubert        )
993*a466cc55SCy Schubert        return code.split("\n")
9942b15cb3dSCy Schubert
9952b15cb3dSCy Schubert    def CodeComplete(self, structname, var_name):
996*a466cc55SCy Schubert        code = [
997*a466cc55SCy Schubert            "if (%(structname)s->%(name)s_set && "
998*a466cc55SCy Schubert            "%(refname)s_complete(%(var)s) == -1)",
999*a466cc55SCy Schubert            "  return (-1);",
10002b15cb3dSCy Schubert        ]
10012b15cb3dSCy Schubert
1002*a466cc55SCy Schubert        return TranslateList(
1003*a466cc55SCy Schubert            code, self.GetTranslation({"structname": structname, "var": var_name})
1004*a466cc55SCy Schubert        )
1005*a466cc55SCy Schubert
1006*a466cc55SCy Schubert    def CodeUnmarshal(self, buf, tag_name, var_name, _var_len):
1007*a466cc55SCy Schubert        code = [
1008*a466cc55SCy Schubert            "%(var)s = %(refname)s_new();",
1009*a466cc55SCy Schubert            "if (%(var)s == NULL)",
1010*a466cc55SCy Schubert            "  return (-1);",
1011*a466cc55SCy Schubert            "if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag)s, ",
1012*a466cc55SCy Schubert            "    %(var)s) == -1) {",
1013*a466cc55SCy Schubert            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
1014*a466cc55SCy Schubert            "  return (-1);",
1015*a466cc55SCy Schubert            "}",
1016*a466cc55SCy Schubert        ]
1017*a466cc55SCy Schubert        code = "\n".join(code) % self.GetTranslation(
1018*a466cc55SCy Schubert            {"buf": buf, "tag": tag_name, "var": var_name}
1019*a466cc55SCy Schubert        )
1020*a466cc55SCy Schubert        return code.split("\n")
1021*a466cc55SCy Schubert
1022*a466cc55SCy Schubert    def CodeMarshal(self, buf, tag_name, var_name, _var_len):
1023*a466cc55SCy Schubert        code = [
1024*a466cc55SCy Schubert            "evtag_marshal_%s(%s, %s, %s);" % (self._refname, buf, tag_name, var_name)
1025*a466cc55SCy Schubert        ]
10262b15cb3dSCy Schubert        return code
10272b15cb3dSCy Schubert
10282b15cb3dSCy Schubert    def CodeClear(self, structname):
1029*a466cc55SCy Schubert        code = [
1030*a466cc55SCy Schubert            "if (%s->%s_set == 1) {" % (structname, self.Name()),
1031*a466cc55SCy Schubert            "  %s_free(%s->%s_data);" % (self._refname, structname, self.Name()),
1032*a466cc55SCy Schubert            "  %s->%s_data = NULL;" % (structname, self.Name()),
1033*a466cc55SCy Schubert            "  %s->%s_set = 0;" % (structname, self.Name()),
1034*a466cc55SCy Schubert            "}",
10352b15cb3dSCy Schubert        ]
10362b15cb3dSCy Schubert
10372b15cb3dSCy Schubert        return code
10382b15cb3dSCy Schubert
10392b15cb3dSCy Schubert    def CodeInitialize(self, name):
1040*a466cc55SCy Schubert        code = ["%s->%s_data = NULL;" % (name, self._name)]
10412b15cb3dSCy Schubert        return code
10422b15cb3dSCy Schubert
10432b15cb3dSCy Schubert    def CodeFree(self, name):
1044*a466cc55SCy Schubert        code = [
1045*a466cc55SCy Schubert            "if (%s->%s_data != NULL)" % (name, self._name),
1046*a466cc55SCy Schubert            "    %s_free(%s->%s_data);" % (self._refname, name, self._name),
1047*a466cc55SCy Schubert        ]
10482b15cb3dSCy Schubert
10492b15cb3dSCy Schubert        return code
10502b15cb3dSCy Schubert
10512b15cb3dSCy Schubert    def Declaration(self):
1052*a466cc55SCy Schubert        dcl = ["%s %s_data;" % (self._ctype, self._name)]
10532b15cb3dSCy Schubert
10542b15cb3dSCy Schubert        return dcl
10552b15cb3dSCy Schubert
1056*a466cc55SCy Schubert
10572b15cb3dSCy Schubertclass EntryVarBytes(Entry):
1058*a466cc55SCy Schubert    def __init__(self, ent_type, name, tag):
10592b15cb3dSCy Schubert        # Init base class
1060*a466cc55SCy Schubert        super(EntryVarBytes, self).__init__(ent_type, name, tag)
10612b15cb3dSCy Schubert
1062*a466cc55SCy Schubert        self._ctype = "ev_uint8_t *"
10632b15cb3dSCy Schubert
1064*a466cc55SCy Schubert    @staticmethod
1065*a466cc55SCy Schubert    def GetInitializer():
10662b15cb3dSCy Schubert        return "NULL"
10672b15cb3dSCy Schubert
10682b15cb3dSCy Schubert    def GetVarLen(self, var):
1069*a466cc55SCy Schubert        return "%(var)s->%(name)s_length" % self.GetTranslation({"var": var})
10702b15cb3dSCy Schubert
1071*a466cc55SCy Schubert    @staticmethod
1072*a466cc55SCy Schubert    def CodeArrayAdd(varname, _value):
10732b15cb3dSCy Schubert        # xxx: copy
1074*a466cc55SCy Schubert        return ["%(varname)s = NULL;" % {"varname": varname}]
10752b15cb3dSCy Schubert
10762b15cb3dSCy Schubert    def GetDeclaration(self, funcname):
1077*a466cc55SCy Schubert        code = [
1078*a466cc55SCy Schubert            "int %s(struct %s *, %s *, ev_uint32_t *);"
1079*a466cc55SCy Schubert            % (funcname, self._struct.Name(), self._ctype)
1080*a466cc55SCy Schubert        ]
10812b15cb3dSCy Schubert        return code
10822b15cb3dSCy Schubert
10832b15cb3dSCy Schubert    def AssignDeclaration(self, funcname):
1084*a466cc55SCy Schubert        code = [
1085*a466cc55SCy Schubert            "int %s(struct %s *, const %s, ev_uint32_t);"
1086*a466cc55SCy Schubert            % (funcname, self._struct.Name(), self._ctype)
1087*a466cc55SCy Schubert        ]
10882b15cb3dSCy Schubert        return code
10892b15cb3dSCy Schubert
10902b15cb3dSCy Schubert    def CodeAssign(self):
10912b15cb3dSCy Schubert        name = self._name
1092*a466cc55SCy Schubert        code = [
1093*a466cc55SCy Schubert            "int",
1094*a466cc55SCy Schubert            "%s_%s_assign(struct %s *msg, "
1095*a466cc55SCy Schubert            "const %s value, ev_uint32_t len)"
1096*a466cc55SCy Schubert            % (self._struct.Name(), name, self._struct.Name(), self._ctype),
1097*a466cc55SCy Schubert            "{",
1098*a466cc55SCy Schubert            "  if (msg->%s_data != NULL)" % name,
1099*a466cc55SCy Schubert            "    free (msg->%s_data);" % name,
1100*a466cc55SCy Schubert            "  msg->%s_data = malloc(len);" % name,
1101*a466cc55SCy Schubert            "  if (msg->%s_data == NULL)" % name,
1102*a466cc55SCy Schubert            "    return (-1);",
1103*a466cc55SCy Schubert            "  msg->%s_set = 1;" % name,
1104*a466cc55SCy Schubert            "  msg->%s_length = len;" % name,
1105*a466cc55SCy Schubert            "  memcpy(msg->%s_data, value, len);" % name,
1106*a466cc55SCy Schubert            "  return (0);",
1107*a466cc55SCy Schubert            "}",
1108*a466cc55SCy Schubert        ]
11092b15cb3dSCy Schubert        return code
11102b15cb3dSCy Schubert
11112b15cb3dSCy Schubert    def CodeGet(self):
11122b15cb3dSCy Schubert        name = self._name
1113*a466cc55SCy Schubert        code = [
1114*a466cc55SCy Schubert            "int",
1115*a466cc55SCy Schubert            "%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)"
1116*a466cc55SCy Schubert            % (self._struct.Name(), name, self._struct.Name(), self._ctype),
1117*a466cc55SCy Schubert            "{",
1118*a466cc55SCy Schubert            "  if (msg->%s_set != 1)" % name,
1119*a466cc55SCy Schubert            "    return (-1);",
1120*a466cc55SCy Schubert            "  *value = msg->%s_data;" % name,
1121*a466cc55SCy Schubert            "  *plen = msg->%s_length;" % name,
1122*a466cc55SCy Schubert            "  return (0);",
1123*a466cc55SCy Schubert            "}",
1124*a466cc55SCy Schubert        ]
11252b15cb3dSCy Schubert        return code
11262b15cb3dSCy Schubert
11272b15cb3dSCy Schubert    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
1128*a466cc55SCy Schubert        code = [
1129*a466cc55SCy Schubert            "if (evtag_payload_length(%(buf)s, &%(varlen)s) == -1)",
1130*a466cc55SCy Schubert            "  return (-1);",
11312b15cb3dSCy Schubert            # We do not want DoS opportunities
1132*a466cc55SCy Schubert            "if (%(varlen)s > evbuffer_get_length(%(buf)s))",
1133*a466cc55SCy Schubert            "  return (-1);",
1134*a466cc55SCy Schubert            "if ((%(var)s = malloc(%(varlen)s)) == NULL)",
1135*a466cc55SCy Schubert            "  return (-1);",
1136*a466cc55SCy Schubert            "if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, %(var)s, "
1137*a466cc55SCy Schubert            "%(varlen)s) == -1) {",
11382b15cb3dSCy Schubert            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
1139*a466cc55SCy Schubert            "  return (-1);",
1140*a466cc55SCy Schubert            "}",
11412b15cb3dSCy Schubert        ]
1142*a466cc55SCy Schubert        code = "\n".join(code) % self.GetTranslation(
1143*a466cc55SCy Schubert            {"buf": buf, "tag": tag_name, "var": var_name, "varlen": var_len}
1144*a466cc55SCy Schubert        )
1145*a466cc55SCy Schubert        return code.split("\n")
11462b15cb3dSCy Schubert
1147*a466cc55SCy Schubert    @staticmethod
1148*a466cc55SCy Schubert    def CodeMarshal(buf, tag_name, var_name, var_len):
1149*a466cc55SCy Schubert        code = ["evtag_marshal(%s, %s, %s, %s);" % (buf, tag_name, var_name, var_len)]
11502b15cb3dSCy Schubert        return code
11512b15cb3dSCy Schubert
11522b15cb3dSCy Schubert    def CodeClear(self, structname):
1153*a466cc55SCy Schubert        code = [
1154*a466cc55SCy Schubert            "if (%s->%s_set == 1) {" % (structname, self.Name()),
1155*a466cc55SCy Schubert            "  free (%s->%s_data);" % (structname, self.Name()),
1156*a466cc55SCy Schubert            "  %s->%s_data = NULL;" % (structname, self.Name()),
1157*a466cc55SCy Schubert            "  %s->%s_length = 0;" % (structname, self.Name()),
1158*a466cc55SCy Schubert            "  %s->%s_set = 0;" % (structname, self.Name()),
1159*a466cc55SCy Schubert            "}",
11602b15cb3dSCy Schubert        ]
11612b15cb3dSCy Schubert
11622b15cb3dSCy Schubert        return code
11632b15cb3dSCy Schubert
11642b15cb3dSCy Schubert    def CodeInitialize(self, name):
1165*a466cc55SCy Schubert        code = [
1166*a466cc55SCy Schubert            "%s->%s_data = NULL;" % (name, self._name),
1167*a466cc55SCy Schubert            "%s->%s_length = 0;" % (name, self._name),
1168*a466cc55SCy Schubert        ]
11692b15cb3dSCy Schubert        return code
11702b15cb3dSCy Schubert
11712b15cb3dSCy Schubert    def CodeFree(self, name):
1172*a466cc55SCy Schubert        code = [
1173*a466cc55SCy Schubert            "if (%s->%s_data != NULL)" % (name, self._name),
1174*a466cc55SCy Schubert            "    free(%s->%s_data);" % (name, self._name),
1175*a466cc55SCy Schubert        ]
11762b15cb3dSCy Schubert
11772b15cb3dSCy Schubert        return code
11782b15cb3dSCy Schubert
11792b15cb3dSCy Schubert    def Declaration(self):
1180*a466cc55SCy Schubert        dcl = [
1181*a466cc55SCy Schubert            "ev_uint8_t *%s_data;" % self._name,
1182*a466cc55SCy Schubert            "ev_uint32_t %s_length;" % self._name,
1183*a466cc55SCy Schubert        ]
11842b15cb3dSCy Schubert
11852b15cb3dSCy Schubert        return dcl
11862b15cb3dSCy Schubert
1187*a466cc55SCy Schubert
11882b15cb3dSCy Schubertclass EntryArray(Entry):
1189*a466cc55SCy Schubert    _index = None
1190*a466cc55SCy Schubert
11912b15cb3dSCy Schubert    def __init__(self, entry):
11922b15cb3dSCy Schubert        # Init base class
1193*a466cc55SCy Schubert        super(EntryArray, self).__init__(entry._type, entry._name, entry._tag)
11942b15cb3dSCy Schubert
11952b15cb3dSCy Schubert        self._entry = entry
11962b15cb3dSCy Schubert        self._refname = entry._refname
11972b15cb3dSCy Schubert        self._ctype = self._entry._ctype
11982b15cb3dSCy Schubert        self._optional = True
11992b15cb3dSCy Schubert        self._optpointer = self._entry._optpointer
12002b15cb3dSCy Schubert        self._optaddarg = self._entry._optaddarg
12012b15cb3dSCy Schubert
12022b15cb3dSCy Schubert        # provide a new function for accessing the variable name
12032b15cb3dSCy Schubert        def GetVarName(var_name):
1204*a466cc55SCy Schubert            return "%(var)s->%(name)s_data[%(index)s]" % self._entry.GetTranslation(
1205*a466cc55SCy Schubert                {"var": var_name, "index": self._index}
1206*a466cc55SCy Schubert            )
1207*a466cc55SCy Schubert
12082b15cb3dSCy Schubert        self._entry.GetVarName = GetVarName
12092b15cb3dSCy Schubert
12102b15cb3dSCy Schubert    def GetInitializer(self):
12112b15cb3dSCy Schubert        return "NULL"
12122b15cb3dSCy Schubert
1213*a466cc55SCy Schubert    def GetVarName(self, var):
1214*a466cc55SCy Schubert        return var
12152b15cb3dSCy Schubert
1216*a466cc55SCy Schubert    def GetVarLen(self, _var_name):
1217*a466cc55SCy Schubert        return "-1"
12182b15cb3dSCy Schubert
12192b15cb3dSCy Schubert    def GetDeclaration(self, funcname):
12202b15cb3dSCy Schubert        """Allows direct access to elements of the array."""
12212b15cb3dSCy Schubert        code = [
1222*a466cc55SCy Schubert            "int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);"
1223*a466cc55SCy Schubert            % self.GetTranslation({"funcname": funcname})
1224*a466cc55SCy Schubert        ]
12252b15cb3dSCy Schubert        return code
12262b15cb3dSCy Schubert
12272b15cb3dSCy Schubert    def AssignDeclaration(self, funcname):
1228*a466cc55SCy Schubert        code = [
1229*a466cc55SCy Schubert            "int %s(struct %s *, int, const %s);"
1230*a466cc55SCy Schubert            % (funcname, self._struct.Name(), self._ctype)
1231*a466cc55SCy Schubert        ]
12322b15cb3dSCy Schubert        return code
12332b15cb3dSCy Schubert
12342b15cb3dSCy Schubert    def AddDeclaration(self, funcname):
12352b15cb3dSCy Schubert        code = [
1236*a466cc55SCy Schubert            "%(ctype)s %(optpointer)s "
1237*a466cc55SCy Schubert            "%(funcname)s(struct %(parent_name)s *msg%(optaddarg)s);"
1238*a466cc55SCy Schubert            % self.GetTranslation({"funcname": funcname})
1239*a466cc55SCy Schubert        ]
12402b15cb3dSCy Schubert        return code
12412b15cb3dSCy Schubert
12422b15cb3dSCy Schubert    def CodeGet(self):
12432b15cb3dSCy Schubert        code = """int
12442b15cb3dSCy Schubert%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset,
12452b15cb3dSCy Schubert    %(ctype)s *value)
12462b15cb3dSCy Schubert{
12472b15cb3dSCy Schubert  if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length)
12482b15cb3dSCy Schubert    return (-1);
12492b15cb3dSCy Schubert  *value = msg->%(name)s_data[offset];
12502b15cb3dSCy Schubert  return (0);
1251*a466cc55SCy Schubert}
1252*a466cc55SCy Schubert""" % (
1253*a466cc55SCy Schubert            self.GetTranslation()
1254*a466cc55SCy Schubert        )
12552b15cb3dSCy Schubert
1256*a466cc55SCy Schubert        return code.splitlines()
12572b15cb3dSCy Schubert
12582b15cb3dSCy Schubert    def CodeAssign(self):
12592b15cb3dSCy Schubert        code = [
1260*a466cc55SCy Schubert            "int",
1261*a466cc55SCy Schubert            "%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,",
1262*a466cc55SCy Schubert            "  const %(ctype)s value)",
1263*a466cc55SCy Schubert            "{",
1264*a466cc55SCy Schubert            "  if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)",
1265*a466cc55SCy Schubert            "    return (-1);",
1266*a466cc55SCy Schubert            "",
1267*a466cc55SCy Schubert            "  {",
1268*a466cc55SCy Schubert        ]
12692b15cb3dSCy Schubert        code = TranslateList(code, self.GetTranslation())
12702b15cb3dSCy Schubert
12712b15cb3dSCy Schubert        codearrayassign = self._entry.CodeArrayAssign(
1272*a466cc55SCy Schubert            "msg->%(name)s_data[off]" % self.GetTranslation(), "value"
1273*a466cc55SCy Schubert        )
1274*a466cc55SCy Schubert        code += ["    " + x for x in codearrayassign]
12752b15cb3dSCy Schubert
1276*a466cc55SCy Schubert        code += TranslateList(["  }", "  return (0);", "}"], self.GetTranslation())
12772b15cb3dSCy Schubert
12782b15cb3dSCy Schubert        return code
12792b15cb3dSCy Schubert
12802b15cb3dSCy Schubert    def CodeAdd(self):
12812b15cb3dSCy Schubert        codearrayadd = self._entry.CodeArrayAdd(
1282*a466cc55SCy Schubert            "msg->%(name)s_data[msg->%(name)s_length - 1]" % self.GetTranslation(),
1283*a466cc55SCy Schubert            "value",
1284*a466cc55SCy Schubert        )
12852b15cb3dSCy Schubert        code = [
1286*a466cc55SCy Schubert            "static int",
1287*a466cc55SCy Schubert            "%(parent_name)s_%(name)s_expand_to_hold_more("
1288*a466cc55SCy Schubert            "struct %(parent_name)s *msg)",
1289*a466cc55SCy Schubert            "{",
1290*a466cc55SCy Schubert            "  int tobe_allocated = msg->%(name)s_num_allocated;",
1291*a466cc55SCy Schubert            "  %(ctype)s* new_data = NULL;",
1292*a466cc55SCy Schubert            "  tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;",
1293*a466cc55SCy Schubert            "  new_data = (%(ctype)s*) realloc(msg->%(name)s_data,",
1294*a466cc55SCy Schubert            "      tobe_allocated * sizeof(%(ctype)s));",
1295*a466cc55SCy Schubert            "  if (new_data == NULL)",
1296*a466cc55SCy Schubert            "    return -1;",
1297*a466cc55SCy Schubert            "  msg->%(name)s_data = new_data;",
1298*a466cc55SCy Schubert            "  msg->%(name)s_num_allocated = tobe_allocated;",
1299*a466cc55SCy Schubert            "  return 0;",
1300*a466cc55SCy Schubert            "}",
1301*a466cc55SCy Schubert            "",
1302*a466cc55SCy Schubert            "%(ctype)s %(optpointer)s",
1303*a466cc55SCy Schubert            "%(parent_name)s_%(name)s_add(struct %(parent_name)s *msg%(optaddarg)s)",
1304*a466cc55SCy Schubert            "{",
1305*a466cc55SCy Schubert            "  if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {",
1306*a466cc55SCy Schubert            "    if (%(parent_name)s_%(name)s_expand_to_hold_more(msg)<0)",
1307*a466cc55SCy Schubert            "      goto error;",
1308*a466cc55SCy Schubert            "  }",
1309*a466cc55SCy Schubert        ]
13102b15cb3dSCy Schubert
13112b15cb3dSCy Schubert        code = TranslateList(code, self.GetTranslation())
13122b15cb3dSCy Schubert
1313*a466cc55SCy Schubert        code += ["  " + x for x in codearrayadd]
13142b15cb3dSCy Schubert
1315*a466cc55SCy Schubert        code += TranslateList(
1316*a466cc55SCy Schubert            [
1317*a466cc55SCy Schubert                "  msg->%(name)s_set = 1;",
1318*a466cc55SCy Schubert                "  return %(optreference)s(msg->%(name)s_data["
1319*a466cc55SCy Schubert                "msg->%(name)s_length - 1]);",
1320*a466cc55SCy Schubert                "error:",
1321*a466cc55SCy Schubert                "  --msg->%(name)s_length;",
1322*a466cc55SCy Schubert                "  return (NULL);",
1323*a466cc55SCy Schubert                "}",
1324*a466cc55SCy Schubert            ],
1325*a466cc55SCy Schubert            self.GetTranslation(),
1326*a466cc55SCy Schubert        )
13272b15cb3dSCy Schubert
13282b15cb3dSCy Schubert        return code
13292b15cb3dSCy Schubert
13302b15cb3dSCy Schubert    def CodeComplete(self, structname, var_name):
1331*a466cc55SCy Schubert        self._index = "i"
13322b15cb3dSCy Schubert        tmp = self._entry.CodeComplete(structname, self._entry.GetVarName(var_name))
13332b15cb3dSCy Schubert        # skip the whole loop if there is nothing to check
13342b15cb3dSCy Schubert        if not tmp:
13352b15cb3dSCy Schubert            return []
13362b15cb3dSCy Schubert
1337*a466cc55SCy Schubert        translate = self.GetTranslation({"structname": structname})
13382b15cb3dSCy Schubert        code = [
1339*a466cc55SCy Schubert            "{",
1340*a466cc55SCy Schubert            "  int i;",
1341*a466cc55SCy Schubert            "  for (i = 0; i < %(structname)s->%(name)s_length; ++i) {",
1342*a466cc55SCy Schubert        ]
13432b15cb3dSCy Schubert
13442b15cb3dSCy Schubert        code = TranslateList(code, translate)
13452b15cb3dSCy Schubert
1346*a466cc55SCy Schubert        code += ["    " + x for x in tmp]
13472b15cb3dSCy Schubert
1348*a466cc55SCy Schubert        code += ["  }", "}"]
13492b15cb3dSCy Schubert
13502b15cb3dSCy Schubert        return code
13512b15cb3dSCy Schubert
1352*a466cc55SCy Schubert    def CodeUnmarshal(self, buf, tag_name, var_name, _var_len):
1353*a466cc55SCy Schubert        translate = self.GetTranslation(
1354*a466cc55SCy Schubert            {
1355*a466cc55SCy Schubert                "var": var_name,
1356*a466cc55SCy Schubert                "buf": buf,
1357*a466cc55SCy Schubert                "tag": tag_name,
1358*a466cc55SCy Schubert                "init": self._entry.GetInitializer(),
1359*a466cc55SCy Schubert            }
1360*a466cc55SCy Schubert        )
13612b15cb3dSCy Schubert        code = [
1362*a466cc55SCy Schubert            "if (%(var)s->%(name)s_length >= %(var)s->%(name)s_num_allocated &&",
1363*a466cc55SCy Schubert            "    %(parent_name)s_%(name)s_expand_to_hold_more(%(var)s) < 0) {",
13642b15cb3dSCy Schubert            '  puts("HEY NOW");',
1365*a466cc55SCy Schubert            "  return (-1);",
1366*a466cc55SCy Schubert            "}",
1367*a466cc55SCy Schubert        ]
13682b15cb3dSCy Schubert
13692b15cb3dSCy Schubert        # the unmarshal code directly returns
13702b15cb3dSCy Schubert        code = TranslateList(code, translate)
13712b15cb3dSCy Schubert
1372*a466cc55SCy Schubert        self._index = "%(var)s->%(name)s_length" % translate
1373*a466cc55SCy Schubert        code += self._entry.CodeUnmarshal(
1374*a466cc55SCy Schubert            buf,
1375*a466cc55SCy Schubert            tag_name,
13762b15cb3dSCy Schubert            self._entry.GetVarName(var_name),
1377*a466cc55SCy Schubert            self._entry.GetVarLen(var_name),
1378*a466cc55SCy Schubert        )
13792b15cb3dSCy Schubert
1380*a466cc55SCy Schubert        code += ["++%(var)s->%(name)s_length;" % translate]
13812b15cb3dSCy Schubert
13822b15cb3dSCy Schubert        return code
13832b15cb3dSCy Schubert
1384*a466cc55SCy Schubert    def CodeMarshal(self, buf, tag_name, var_name, _var_len):
1385*a466cc55SCy Schubert        code = ["{", "  int i;", "  for (i = 0; i < %(var)s->%(name)s_length; ++i) {"]
13862b15cb3dSCy Schubert
1387*a466cc55SCy Schubert        self._index = "i"
1388*a466cc55SCy Schubert        code += self._entry.CodeMarshal(
1389*a466cc55SCy Schubert            buf,
1390*a466cc55SCy Schubert            tag_name,
13912b15cb3dSCy Schubert            self._entry.GetVarName(var_name),
1392*a466cc55SCy Schubert            self._entry.GetVarLen(var_name),
1393*a466cc55SCy Schubert        )
1394*a466cc55SCy Schubert        code += ["  }", "}"]
13952b15cb3dSCy Schubert
1396*a466cc55SCy Schubert        code = "\n".join(code) % self.GetTranslation({"var": var_name})
13972b15cb3dSCy Schubert
1398*a466cc55SCy Schubert        return code.split("\n")
13992b15cb3dSCy Schubert
14002b15cb3dSCy Schubert    def CodeClear(self, structname):
1401*a466cc55SCy Schubert        translate = self.GetTranslation({"structname": structname})
14022b15cb3dSCy Schubert        codearrayfree = self._entry.CodeArrayFree(
1403*a466cc55SCy Schubert            "%(structname)s->%(name)s_data[i]"
1404*a466cc55SCy Schubert            % self.GetTranslation({"structname": structname})
1405*a466cc55SCy Schubert        )
14062b15cb3dSCy Schubert
1407*a466cc55SCy Schubert        code = ["if (%(structname)s->%(name)s_set == 1) {"]
14082b15cb3dSCy Schubert
14092b15cb3dSCy Schubert        if codearrayfree:
14102b15cb3dSCy Schubert            code += [
1411*a466cc55SCy Schubert                "  int i;",
1412*a466cc55SCy Schubert                "  for (i = 0; i < %(structname)s->%(name)s_length; ++i) {",
1413*a466cc55SCy Schubert            ]
14142b15cb3dSCy Schubert
14152b15cb3dSCy Schubert        code = TranslateList(code, translate)
14162b15cb3dSCy Schubert
14172b15cb3dSCy Schubert        if codearrayfree:
1418*a466cc55SCy Schubert            code += ["    " + x for x in codearrayfree]
1419*a466cc55SCy Schubert            code += ["  }"]
14202b15cb3dSCy Schubert
1421*a466cc55SCy Schubert        code += TranslateList(
1422*a466cc55SCy Schubert            [
1423*a466cc55SCy Schubert                "  free(%(structname)s->%(name)s_data);",
1424*a466cc55SCy Schubert                "  %(structname)s->%(name)s_data = NULL;",
1425*a466cc55SCy Schubert                "  %(structname)s->%(name)s_set = 0;",
1426*a466cc55SCy Schubert                "  %(structname)s->%(name)s_length = 0;",
1427*a466cc55SCy Schubert                "  %(structname)s->%(name)s_num_allocated = 0;",
1428*a466cc55SCy Schubert                "}",
1429*a466cc55SCy Schubert            ],
1430*a466cc55SCy Schubert            translate,
1431*a466cc55SCy Schubert        )
14322b15cb3dSCy Schubert
14332b15cb3dSCy Schubert        return code
14342b15cb3dSCy Schubert
14352b15cb3dSCy Schubert    def CodeInitialize(self, name):
1436*a466cc55SCy Schubert        code = [
1437*a466cc55SCy Schubert            "%s->%s_data = NULL;" % (name, self._name),
1438*a466cc55SCy Schubert            "%s->%s_length = 0;" % (name, self._name),
1439*a466cc55SCy Schubert            "%s->%s_num_allocated = 0;" % (name, self._name),
1440*a466cc55SCy Schubert        ]
14412b15cb3dSCy Schubert        return code
14422b15cb3dSCy Schubert
14432b15cb3dSCy Schubert    def CodeFree(self, structname):
1444*a466cc55SCy Schubert        code = self.CodeClear(structname)
14452b15cb3dSCy Schubert
1446*a466cc55SCy Schubert        code += TranslateList(
1447*a466cc55SCy Schubert            ["free(%(structname)s->%(name)s_data);"],
1448*a466cc55SCy Schubert            self.GetTranslation({"structname": structname}),
1449*a466cc55SCy Schubert        )
14502b15cb3dSCy Schubert
14512b15cb3dSCy Schubert        return code
14522b15cb3dSCy Schubert
14532b15cb3dSCy Schubert    def Declaration(self):
1454*a466cc55SCy Schubert        dcl = [
1455*a466cc55SCy Schubert            "%s *%s_data;" % (self._ctype, self._name),
1456*a466cc55SCy Schubert            "int %s_length;" % self._name,
1457*a466cc55SCy Schubert            "int %s_num_allocated;" % self._name,
1458*a466cc55SCy Schubert        ]
14592b15cb3dSCy Schubert
14602b15cb3dSCy Schubert        return dcl
14612b15cb3dSCy Schubert
14622b15cb3dSCy Schubert
1463*a466cc55SCy Schubertdef NormalizeLine(line):
1464*a466cc55SCy Schubert
1465*a466cc55SCy Schubert    line = CPPCOMMENT_RE.sub("", line)
14662b15cb3dSCy Schubert    line = line.strip()
1467*a466cc55SCy Schubert    line = WHITESPACE_RE.sub(" ", line)
14682b15cb3dSCy Schubert
14692b15cb3dSCy Schubert    return line
14702b15cb3dSCy Schubert
1471*a466cc55SCy Schubert
1472*a466cc55SCy SchubertENTRY_NAME_RE = re.compile(r"(?P<name>[^\[\]]+)(\[(?P<fixed_length>.*)\])?")
1473*a466cc55SCy SchubertENTRY_TAG_NUMBER_RE = re.compile(r"(0x)?\d+", re.I)
1474*a466cc55SCy Schubert
1475*a466cc55SCy Schubert
14762b15cb3dSCy Schubertdef ProcessOneEntry(factory, newstruct, entry):
1477*a466cc55SCy Schubert    optional = False
1478*a466cc55SCy Schubert    array = False
1479*a466cc55SCy Schubert    entry_type = ""
1480*a466cc55SCy Schubert    name = ""
1481*a466cc55SCy Schubert    tag = ""
14822b15cb3dSCy Schubert    tag_set = None
1483*a466cc55SCy Schubert    separator = ""
1484*a466cc55SCy Schubert    fixed_length = ""
14852b15cb3dSCy Schubert
1486*a466cc55SCy Schubert    for token in entry.split(" "):
14872b15cb3dSCy Schubert        if not entry_type:
1488*a466cc55SCy Schubert            if not optional and token == "optional":
1489*a466cc55SCy Schubert                optional = True
14902b15cb3dSCy Schubert                continue
14912b15cb3dSCy Schubert
1492*a466cc55SCy Schubert            if not array and token == "array":
1493*a466cc55SCy Schubert                array = True
14942b15cb3dSCy Schubert                continue
14952b15cb3dSCy Schubert
14962b15cb3dSCy Schubert        if not entry_type:
14972b15cb3dSCy Schubert            entry_type = token
14982b15cb3dSCy Schubert            continue
14992b15cb3dSCy Schubert
15002b15cb3dSCy Schubert        if not name:
1501*a466cc55SCy Schubert            res = ENTRY_NAME_RE.match(token)
15022b15cb3dSCy Schubert            if not res:
15032b15cb3dSCy Schubert                raise RpcGenError(
1504*a466cc55SCy Schubert                    r"""Cannot parse name: "%s" around line %d""" % (entry, LINE_COUNT)
1505*a466cc55SCy Schubert                )
1506*a466cc55SCy Schubert            name = res.group("name")
1507*a466cc55SCy Schubert            fixed_length = res.group("fixed_length")
15082b15cb3dSCy Schubert            continue
15092b15cb3dSCy Schubert
15102b15cb3dSCy Schubert        if not separator:
15112b15cb3dSCy Schubert            separator = token
1512*a466cc55SCy Schubert            if separator != "=":
1513*a466cc55SCy Schubert                raise RpcGenError(
1514*a466cc55SCy Schubert                    r'''Expected "=" after name "%s" got "%s"''' % (name, token)
1515*a466cc55SCy Schubert                )
15162b15cb3dSCy Schubert            continue
15172b15cb3dSCy Schubert
15182b15cb3dSCy Schubert        if not tag_set:
15192b15cb3dSCy Schubert            tag_set = 1
1520*a466cc55SCy Schubert            if not ENTRY_TAG_NUMBER_RE.match(token):
1521*a466cc55SCy Schubert                raise RpcGenError(r'''Expected tag number: "%s"''' % (entry))
15222b15cb3dSCy Schubert            tag = int(token, 0)
15232b15cb3dSCy Schubert            continue
15242b15cb3dSCy Schubert
1525*a466cc55SCy Schubert        raise RpcGenError(r'''Cannot parse "%s"''' % (entry))
15262b15cb3dSCy Schubert
15272b15cb3dSCy Schubert    if not tag_set:
1528*a466cc55SCy Schubert        raise RpcGenError(r'''Need tag number: "%s"''' % (entry))
15292b15cb3dSCy Schubert
15302b15cb3dSCy Schubert    # Create the right entry
1531*a466cc55SCy Schubert    if entry_type == "bytes":
15322b15cb3dSCy Schubert        if fixed_length:
15332b15cb3dSCy Schubert            newentry = factory.EntryBytes(entry_type, name, tag, fixed_length)
15342b15cb3dSCy Schubert        else:
15352b15cb3dSCy Schubert            newentry = factory.EntryVarBytes(entry_type, name, tag)
1536*a466cc55SCy Schubert    elif entry_type == "int" and not fixed_length:
15372b15cb3dSCy Schubert        newentry = factory.EntryInt(entry_type, name, tag)
1538*a466cc55SCy Schubert    elif entry_type == "int64" and not fixed_length:
15392b15cb3dSCy Schubert        newentry = factory.EntryInt(entry_type, name, tag, bits=64)
1540*a466cc55SCy Schubert    elif entry_type == "string" and not fixed_length:
15412b15cb3dSCy Schubert        newentry = factory.EntryString(entry_type, name, tag)
15422b15cb3dSCy Schubert    else:
1543*a466cc55SCy Schubert        res = STRUCT_REF_RE.match(entry_type)
15442b15cb3dSCy Schubert        if res:
15452b15cb3dSCy Schubert            # References another struct defined in our file
1546*a466cc55SCy Schubert            newentry = factory.EntryStruct(entry_type, name, tag, res.group("name"))
15472b15cb3dSCy Schubert        else:
15482b15cb3dSCy Schubert            raise RpcGenError('Bad type: "%s" in "%s"' % (entry_type, entry))
15492b15cb3dSCy Schubert
15502b15cb3dSCy Schubert    structs = []
15512b15cb3dSCy Schubert
15522b15cb3dSCy Schubert    if optional:
15532b15cb3dSCy Schubert        newentry.MakeOptional()
15542b15cb3dSCy Schubert    if array:
15552b15cb3dSCy Schubert        newentry.MakeArray()
15562b15cb3dSCy Schubert
15572b15cb3dSCy Schubert    newentry.SetStruct(newstruct)
1558*a466cc55SCy Schubert    newentry.SetLineCount(LINE_COUNT)
15592b15cb3dSCy Schubert    newentry.Verify()
15602b15cb3dSCy Schubert
15612b15cb3dSCy Schubert    if array:
15622b15cb3dSCy Schubert        # We need to encapsulate this entry into a struct
15632b15cb3dSCy Schubert        newentry = factory.EntryArray(newentry)
15642b15cb3dSCy Schubert        newentry.SetStruct(newstruct)
1565*a466cc55SCy Schubert        newentry.SetLineCount(LINE_COUNT)
15662b15cb3dSCy Schubert        newentry.MakeArray()
15672b15cb3dSCy Schubert
15682b15cb3dSCy Schubert    newstruct.AddEntry(newentry)
15692b15cb3dSCy Schubert
15702b15cb3dSCy Schubert    return structs
15712b15cb3dSCy Schubert
1572*a466cc55SCy Schubert
15732b15cb3dSCy Schubertdef ProcessStruct(factory, data):
1574*a466cc55SCy Schubert    tokens = data.split(" ")
15752b15cb3dSCy Schubert
15762b15cb3dSCy Schubert    # First three tokens are: 'struct' 'name' '{'
15772b15cb3dSCy Schubert    newstruct = factory.Struct(tokens[1])
15782b15cb3dSCy Schubert
1579*a466cc55SCy Schubert    inside = " ".join(tokens[3:-1])
15802b15cb3dSCy Schubert
1581*a466cc55SCy Schubert    tokens = inside.split(";")
15822b15cb3dSCy Schubert
15832b15cb3dSCy Schubert    structs = []
15842b15cb3dSCy Schubert
15852b15cb3dSCy Schubert    for entry in tokens:
15862b15cb3dSCy Schubert        entry = NormalizeLine(entry)
15872b15cb3dSCy Schubert        if not entry:
15882b15cb3dSCy Schubert            continue
15892b15cb3dSCy Schubert
15902b15cb3dSCy Schubert        # It's possible that new structs get defined in here
15912b15cb3dSCy Schubert        structs.extend(ProcessOneEntry(factory, newstruct, entry))
15922b15cb3dSCy Schubert
15932b15cb3dSCy Schubert    structs.append(newstruct)
15942b15cb3dSCy Schubert    return structs
15952b15cb3dSCy Schubert
15962b15cb3dSCy Schubert
1597*a466cc55SCy SchubertC_COMMENT_START = "/*"
1598*a466cc55SCy SchubertC_COMMENT_END = "*/"
15992b15cb3dSCy Schubert
1600*a466cc55SCy SchubertC_COMMENT_START_RE = re.compile(re.escape(C_COMMENT_START))
1601*a466cc55SCy SchubertC_COMMENT_END_RE = re.compile(re.escape(C_COMMENT_END))
16022b15cb3dSCy Schubert
1603*a466cc55SCy SchubertC_COMMENT_START_SUB_RE = re.compile(r"%s.*$" % (re.escape(C_COMMENT_START)))
1604*a466cc55SCy SchubertC_COMMENT_END_SUB_RE = re.compile(r"%s.*$" % (re.escape(C_COMMENT_END)))
1605*a466cc55SCy Schubert
1606*a466cc55SCy SchubertC_MULTILINE_COMMENT_SUB_RE = re.compile(
1607*a466cc55SCy Schubert    r"%s.*?%s" % (re.escape(C_COMMENT_START), re.escape(C_COMMENT_END))
1608*a466cc55SCy Schubert)
1609*a466cc55SCy SchubertCPP_CONDITIONAL_BLOCK_RE = re.compile(r"#(if( |def)|endif)")
1610*a466cc55SCy SchubertINCLUDE_RE = re.compile(r'#include (".+"|<.+>)')
1611*a466cc55SCy Schubert
1612*a466cc55SCy Schubert
1613*a466cc55SCy Schubertdef GetNextStruct(filep):
1614*a466cc55SCy Schubert    global CPP_DIRECT
1615*a466cc55SCy Schubert    global LINE_COUNT
1616*a466cc55SCy Schubert
1617*a466cc55SCy Schubert    got_struct = False
1618*a466cc55SCy Schubert    have_c_comment = False
1619*a466cc55SCy Schubert
1620*a466cc55SCy Schubert    data = ""
1621*a466cc55SCy Schubert
1622*a466cc55SCy Schubert    while True:
1623*a466cc55SCy Schubert        line = filep.readline()
16242b15cb3dSCy Schubert        if not line:
16252b15cb3dSCy Schubert            break
16262b15cb3dSCy Schubert
1627*a466cc55SCy Schubert        LINE_COUNT += 1
16282b15cb3dSCy Schubert        line = line[:-1]
16292b15cb3dSCy Schubert
1630*a466cc55SCy Schubert        if not have_c_comment and C_COMMENT_START_RE.search(line):
1631*a466cc55SCy Schubert            if C_MULTILINE_COMMENT_SUB_RE.search(line):
1632*a466cc55SCy Schubert                line = C_MULTILINE_COMMENT_SUB_RE.sub("", line)
16332b15cb3dSCy Schubert            else:
1634*a466cc55SCy Schubert                line = C_COMMENT_START_SUB_RE.sub("", line)
1635*a466cc55SCy Schubert                have_c_comment = True
16362b15cb3dSCy Schubert
16372b15cb3dSCy Schubert        if have_c_comment:
1638*a466cc55SCy Schubert            if not C_COMMENT_END_RE.search(line):
16392b15cb3dSCy Schubert                continue
1640*a466cc55SCy Schubert            have_c_comment = False
1641*a466cc55SCy Schubert            line = C_COMMENT_END_SUB_RE.sub("", line)
16422b15cb3dSCy Schubert
16432b15cb3dSCy Schubert        line = NormalizeLine(line)
16442b15cb3dSCy Schubert
16452b15cb3dSCy Schubert        if not line:
16462b15cb3dSCy Schubert            continue
16472b15cb3dSCy Schubert
16482b15cb3dSCy Schubert        if not got_struct:
1649*a466cc55SCy Schubert            if INCLUDE_RE.match(line):
1650*a466cc55SCy Schubert                CPP_DIRECT.append(line)
1651*a466cc55SCy Schubert            elif CPP_CONDITIONAL_BLOCK_RE.match(line):
1652*a466cc55SCy Schubert                CPP_DIRECT.append(line)
1653*a466cc55SCy Schubert            elif PREPROCESSOR_DEF_RE.match(line):
1654*a466cc55SCy Schubert                HEADER_DIRECT.append(line)
1655*a466cc55SCy Schubert            elif not STRUCT_DEF_RE.match(line):
1656*a466cc55SCy Schubert                raise RpcGenError("Missing struct on line %d: %s" % (LINE_COUNT, line))
16572b15cb3dSCy Schubert            else:
1658*a466cc55SCy Schubert                got_struct = True
16592b15cb3dSCy Schubert                data += line
16602b15cb3dSCy Schubert            continue
16612b15cb3dSCy Schubert
16622b15cb3dSCy Schubert        # We are inside the struct
1663*a466cc55SCy Schubert        tokens = line.split("}")
16642b15cb3dSCy Schubert        if len(tokens) == 1:
1665*a466cc55SCy Schubert            data += " " + line
16662b15cb3dSCy Schubert            continue
16672b15cb3dSCy Schubert
1668*a466cc55SCy Schubert        if tokens[1]:
1669*a466cc55SCy Schubert            raise RpcGenError("Trailing garbage after struct on line %d" % LINE_COUNT)
16702b15cb3dSCy Schubert
16712b15cb3dSCy Schubert        # We found the end of the struct
1672*a466cc55SCy Schubert        data += " %s}" % tokens[0]
16732b15cb3dSCy Schubert        break
16742b15cb3dSCy Schubert
16752b15cb3dSCy Schubert    # Remove any comments, that might be in there
1676*a466cc55SCy Schubert    data = re.sub(r"/\*.*\*/", "", data)
16772b15cb3dSCy Schubert
16782b15cb3dSCy Schubert    return data
16792b15cb3dSCy Schubert
16802b15cb3dSCy Schubert
1681*a466cc55SCy Schubertdef Parse(factory, filep):
16822b15cb3dSCy Schubert    """
16832b15cb3dSCy Schubert    Parses the input file and returns C code and corresponding header file.
16842b15cb3dSCy Schubert    """
16852b15cb3dSCy Schubert
16862b15cb3dSCy Schubert    entities = []
16872b15cb3dSCy Schubert
16882b15cb3dSCy Schubert    while 1:
16892b15cb3dSCy Schubert        # Just gets the whole struct nicely formatted
1690*a466cc55SCy Schubert        data = GetNextStruct(filep)
16912b15cb3dSCy Schubert
16922b15cb3dSCy Schubert        if not data:
16932b15cb3dSCy Schubert            break
16942b15cb3dSCy Schubert
16952b15cb3dSCy Schubert        entities.extend(ProcessStruct(factory, data))
16962b15cb3dSCy Schubert
16972b15cb3dSCy Schubert    return entities
16982b15cb3dSCy Schubert
1699*a466cc55SCy Schubert
1700*a466cc55SCy Schubertclass CCodeGenerator(object):
17012b15cb3dSCy Schubert    def __init__(self):
17022b15cb3dSCy Schubert        pass
17032b15cb3dSCy Schubert
1704*a466cc55SCy Schubert    @staticmethod
1705*a466cc55SCy Schubert    def GuardName(name):
17062b15cb3dSCy Schubert        # Use the complete provided path to the input file, with all
17072b15cb3dSCy Schubert        # non-identifier characters replaced with underscores, to
17082b15cb3dSCy Schubert        # reduce the chance of a collision between guard macros.
1709*a466cc55SCy Schubert        return "EVENT_RPCOUT_%s_" % (NONIDENT_RE.sub("_", name).upper())
17102b15cb3dSCy Schubert
17112b15cb3dSCy Schubert    def HeaderPreamble(self, name):
17122b15cb3dSCy Schubert        guard = self.GuardName(name)
1713*a466cc55SCy Schubert        pre = """
1714*a466cc55SCy Schubert/*
1715*a466cc55SCy Schubert * Automatically generated from %s
1716*a466cc55SCy Schubert */
17172b15cb3dSCy Schubert
1718*a466cc55SCy Schubert#ifndef %s
1719*a466cc55SCy Schubert#define %s
17202b15cb3dSCy Schubert
1721*a466cc55SCy Schubert""" % (
1722*a466cc55SCy Schubert            name,
1723*a466cc55SCy Schubert            guard,
1724*a466cc55SCy Schubert            guard,
17252b15cb3dSCy Schubert        )
17262b15cb3dSCy Schubert
1727*a466cc55SCy Schubert        if HEADER_DIRECT:
1728*a466cc55SCy Schubert            for statement in HEADER_DIRECT:
1729*a466cc55SCy Schubert                pre += "%s\n" % statement
1730*a466cc55SCy Schubert            pre += "\n"
1731*a466cc55SCy Schubert
1732*a466cc55SCy Schubert        pre += """
1733*a466cc55SCy Schubert#include <event2/util.h> /* for ev_uint*_t */
1734*a466cc55SCy Schubert#include <event2/rpc.h>
1735*a466cc55SCy Schubert"""
1736*a466cc55SCy Schubert
17372b15cb3dSCy Schubert        return pre
17382b15cb3dSCy Schubert
17392b15cb3dSCy Schubert    def HeaderPostamble(self, name):
17402b15cb3dSCy Schubert        guard = self.GuardName(name)
1741*a466cc55SCy Schubert        return "#endif  /* %s */" % (guard)
17422b15cb3dSCy Schubert
1743*a466cc55SCy Schubert    @staticmethod
1744*a466cc55SCy Schubert    def BodyPreamble(name, header_file):
17452b15cb3dSCy Schubert        global _NAME
17462b15cb3dSCy Schubert        global _VERSION
17472b15cb3dSCy Schubert
1748*a466cc55SCy Schubert        slash = header_file.rfind("/")
17492b15cb3dSCy Schubert        if slash != -1:
17502b15cb3dSCy Schubert            header_file = header_file[slash + 1 :]
17512b15cb3dSCy Schubert
1752*a466cc55SCy Schubert        pre = """
1753*a466cc55SCy Schubert/*
1754*a466cc55SCy Schubert * Automatically generated from %(name)s
1755*a466cc55SCy Schubert * by %(script_name)s/%(script_version)s.  DO NOT EDIT THIS FILE.
1756*a466cc55SCy Schubert */
17572b15cb3dSCy Schubert
1758*a466cc55SCy Schubert#include <stdlib.h>
1759*a466cc55SCy Schubert#include <string.h>
1760*a466cc55SCy Schubert#include <assert.h>
1761*a466cc55SCy Schubert#include <event2/event-config.h>
1762*a466cc55SCy Schubert#include <event2/event.h>
1763*a466cc55SCy Schubert#include <event2/buffer.h>
1764*a466cc55SCy Schubert#include <event2/tag.h>
1765*a466cc55SCy Schubert
1766*a466cc55SCy Schubert#if defined(EVENT__HAVE___func__)
1767*a466cc55SCy Schubert# ifndef __func__
1768*a466cc55SCy Schubert#  define __func__ __func__
1769*a466cc55SCy Schubert# endif
1770*a466cc55SCy Schubert#elif defined(EVENT__HAVE___FUNCTION__)
1771*a466cc55SCy Schubert# define __func__ __FUNCTION__
1772*a466cc55SCy Schubert#else
1773*a466cc55SCy Schubert# define __func__ __FILE__
1774*a466cc55SCy Schubert#endif
1775*a466cc55SCy Schubert
1776*a466cc55SCy Schubert""" % {
1777*a466cc55SCy Schubert            "name": name,
1778*a466cc55SCy Schubert            "script_name": _NAME,
1779*a466cc55SCy Schubert            "script_version": _VERSION,
1780*a466cc55SCy Schubert        }
1781*a466cc55SCy Schubert
1782*a466cc55SCy Schubert        for statement in CPP_DIRECT:
1783*a466cc55SCy Schubert            pre += "%s\n" % statement
17842b15cb3dSCy Schubert
17852b15cb3dSCy Schubert        pre += '\n#include "%s"\n\n' % header_file
17862b15cb3dSCy Schubert
1787*a466cc55SCy Schubert        pre += "void event_warn(const char *fmt, ...);\n"
1788*a466cc55SCy Schubert        pre += "void event_warnx(const char *fmt, ...);\n\n"
17892b15cb3dSCy Schubert
17902b15cb3dSCy Schubert        return pre
17912b15cb3dSCy Schubert
1792*a466cc55SCy Schubert    @staticmethod
1793*a466cc55SCy Schubert    def HeaderFilename(filename):
1794*a466cc55SCy Schubert        return ".".join(filename.split(".")[:-1]) + ".h"
17952b15cb3dSCy Schubert
1796*a466cc55SCy Schubert    @staticmethod
1797*a466cc55SCy Schubert    def CodeFilename(filename):
1798*a466cc55SCy Schubert        return ".".join(filename.split(".")[:-1]) + ".gen.c"
17992b15cb3dSCy Schubert
1800*a466cc55SCy Schubert    @staticmethod
1801*a466cc55SCy Schubert    def Struct(name):
18022b15cb3dSCy Schubert        return StructCCode(name)
18032b15cb3dSCy Schubert
1804*a466cc55SCy Schubert    @staticmethod
1805*a466cc55SCy Schubert    def EntryBytes(entry_type, name, tag, fixed_length):
18062b15cb3dSCy Schubert        return EntryBytes(entry_type, name, tag, fixed_length)
18072b15cb3dSCy Schubert
1808*a466cc55SCy Schubert    @staticmethod
1809*a466cc55SCy Schubert    def EntryVarBytes(entry_type, name, tag):
18102b15cb3dSCy Schubert        return EntryVarBytes(entry_type, name, tag)
18112b15cb3dSCy Schubert
1812*a466cc55SCy Schubert    @staticmethod
1813*a466cc55SCy Schubert    def EntryInt(entry_type, name, tag, bits=32):
18142b15cb3dSCy Schubert        return EntryInt(entry_type, name, tag, bits)
18152b15cb3dSCy Schubert
1816*a466cc55SCy Schubert    @staticmethod
1817*a466cc55SCy Schubert    def EntryString(entry_type, name, tag):
18182b15cb3dSCy Schubert        return EntryString(entry_type, name, tag)
18192b15cb3dSCy Schubert
1820*a466cc55SCy Schubert    @staticmethod
1821*a466cc55SCy Schubert    def EntryStruct(entry_type, name, tag, struct_name):
18222b15cb3dSCy Schubert        return EntryStruct(entry_type, name, tag, struct_name)
18232b15cb3dSCy Schubert
1824*a466cc55SCy Schubert    @staticmethod
1825*a466cc55SCy Schubert    def EntryArray(entry):
18262b15cb3dSCy Schubert        return EntryArray(entry)
18272b15cb3dSCy Schubert
18282b15cb3dSCy Schubert
1829*a466cc55SCy Schubertclass CommandLine(object):
1830*a466cc55SCy Schubert    def __init__(self, argv=None):
18312b15cb3dSCy Schubert        """Initialize a command-line to launch event_rpcgen, as if
18322b15cb3dSCy Schubert           from a command-line with CommandLine(sys.argv).  If you're
18332b15cb3dSCy Schubert           calling this directly, remember to provide a dummy value
18342b15cb3dSCy Schubert           for sys.argv[0]
18352b15cb3dSCy Schubert        """
1836*a466cc55SCy Schubert        global QUIETLY
1837*a466cc55SCy Schubert
18382b15cb3dSCy Schubert        self.filename = None
18392b15cb3dSCy Schubert        self.header_file = None
18402b15cb3dSCy Schubert        self.impl_file = None
18412b15cb3dSCy Schubert        self.factory = CCodeGenerator()
18422b15cb3dSCy Schubert
1843*a466cc55SCy Schubert        parser = argparse.ArgumentParser(
1844*a466cc55SCy Schubert            usage="%(prog)s [options] rpc-file [[h-file] c-file]"
1845*a466cc55SCy Schubert        )
1846*a466cc55SCy Schubert        parser.add_argument("--quiet", action="store_true", default=False)
1847*a466cc55SCy Schubert        parser.add_argument("rpc_file", type=argparse.FileType("r"))
18482b15cb3dSCy Schubert
1849*a466cc55SCy Schubert        args, extra_args = parser.parse_known_args(args=argv)
18502b15cb3dSCy Schubert
1851*a466cc55SCy Schubert        QUIETLY = args.quiet
18522b15cb3dSCy Schubert
1853*a466cc55SCy Schubert        if extra_args:
1854*a466cc55SCy Schubert            if len(extra_args) == 1:
1855*a466cc55SCy Schubert                self.impl_file = extra_args[0].replace("\\", "/")
1856*a466cc55SCy Schubert            elif len(extra_args) == 2:
1857*a466cc55SCy Schubert                self.header_file = extra_args[0].replace("\\", "/")
1858*a466cc55SCy Schubert                self.impl_file = extra_args[1].replace("\\", "/")
1859*a466cc55SCy Schubert            else:
1860*a466cc55SCy Schubert                parser.error("Spurious arguments provided")
1861*a466cc55SCy Schubert
1862*a466cc55SCy Schubert        self.rpc_file = args.rpc_file
18632b15cb3dSCy Schubert
18642b15cb3dSCy Schubert        if not self.impl_file:
1865*a466cc55SCy Schubert            self.impl_file = self.factory.CodeFilename(self.rpc_file.name)
18662b15cb3dSCy Schubert
18672b15cb3dSCy Schubert        if not self.header_file:
18682b15cb3dSCy Schubert            self.header_file = self.factory.HeaderFilename(self.impl_file)
18692b15cb3dSCy Schubert
1870*a466cc55SCy Schubert        if not self.impl_file.endswith(".c"):
1871*a466cc55SCy Schubert            parser.error("can only generate C implementation files")
1872*a466cc55SCy Schubert        if not self.header_file.endswith(".h"):
1873*a466cc55SCy Schubert            parser.error("can only generate C header files")
18742b15cb3dSCy Schubert
18752b15cb3dSCy Schubert    def run(self):
1876*a466cc55SCy Schubert        filename = self.rpc_file.name
18772b15cb3dSCy Schubert        header_file = self.header_file
18782b15cb3dSCy Schubert        impl_file = self.impl_file
18792b15cb3dSCy Schubert        factory = self.factory
18802b15cb3dSCy Schubert
1881*a466cc55SCy Schubert        declare('Reading "%s"' % filename)
18822b15cb3dSCy Schubert
1883*a466cc55SCy Schubert        with self.rpc_file:
1884*a466cc55SCy Schubert            entities = Parse(factory, self.rpc_file)
18852b15cb3dSCy Schubert
18862b15cb3dSCy Schubert        declare('... creating "%s"' % header_file)
1887*a466cc55SCy Schubert        with open(header_file, "w") as header_fp:
1888*a466cc55SCy Schubert            header_fp.write(factory.HeaderPreamble(filename))
18892b15cb3dSCy Schubert
18902b15cb3dSCy Schubert            # Create forward declarations: allows other structs to reference
18912b15cb3dSCy Schubert            # each other
18922b15cb3dSCy Schubert            for entry in entities:
18932b15cb3dSCy Schubert                entry.PrintForwardDeclaration(header_fp)
1894*a466cc55SCy Schubert            header_fp.write("\n")
18952b15cb3dSCy Schubert
18962b15cb3dSCy Schubert            for entry in entities:
18972b15cb3dSCy Schubert                entry.PrintTags(header_fp)
18982b15cb3dSCy Schubert                entry.PrintDeclaration(header_fp)
1899*a466cc55SCy Schubert            header_fp.write(factory.HeaderPostamble(filename))
19002b15cb3dSCy Schubert
19012b15cb3dSCy Schubert        declare('... creating "%s"' % impl_file)
1902*a466cc55SCy Schubert        with open(impl_file, "w") as impl_fp:
1903*a466cc55SCy Schubert            impl_fp.write(factory.BodyPreamble(filename, header_file))
19042b15cb3dSCy Schubert            for entry in entities:
19052b15cb3dSCy Schubert                entry.PrintCode(impl_fp)
19062b15cb3dSCy Schubert
1907*a466cc55SCy Schubert
1908*a466cc55SCy Schubertdef main(argv=None):
19092b15cb3dSCy Schubert    try:
1910*a466cc55SCy Schubert        CommandLine(argv=argv).run()
1911*a466cc55SCy Schubert        return 0
1912*a466cc55SCy Schubert    except RpcGenError as e:
1913*a466cc55SCy Schubert        sys.stderr.write(e)
1914*a466cc55SCy Schubert    except EnvironmentError as e:
19152b15cb3dSCy Schubert        if e.filename and e.strerror:
1916*a466cc55SCy Schubert            sys.stderr.write("%s: %s" % (e.filename, e.strerror))
19172b15cb3dSCy Schubert        elif e.strerror:
1918*a466cc55SCy Schubert            sys.stderr.write(e.strerror)
19192b15cb3dSCy Schubert        else:
19202b15cb3dSCy Schubert            raise
1921*a466cc55SCy Schubert    return 1
1922*a466cc55SCy Schubert
1923*a466cc55SCy Schubert
1924*a466cc55SCy Schubertif __name__ == "__main__":
1925*a466cc55SCy Schubert    sys.exit(main(argv=sys.argv[1:]))
1926