xref: /libevent-2.1.12/event_rpcgen.py (revision 48e04887)
1532a8cc3SKiyoshi Aman#!/usr/bin/env python
2c4e60994SNiels Provos#
3e49e2891SNick Mathewson# Copyright (c) 2005-2007 Niels Provos <[email protected]>
4e49e2891SNick Mathewson# Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
5949cbd12SNiels Provos# All rights reserved.
6949cbd12SNiels Provos#
7226fd50aSNiels Provos# Generates marshaling code based on libevent.
8949cbd12SNiels Provos
9f0ded5f3SAzat Khuzhin# pylint: disable=too-many-lines
10f0ded5f3SAzat Khuzhin# pylint: disable=too-many-branches
11f0ded5f3SAzat Khuzhin# pylint: disable=too-many-public-methods
12f0ded5f3SAzat Khuzhin# pylint: disable=too-many-statements
13f0ded5f3SAzat Khuzhin# pylint: disable=global-statement
146469598eSNiels Provos
15f0ded5f3SAzat Khuzhin# TODO:
16f0ded5f3SAzat Khuzhin# 1) propagate the arguments/options parsed by argparse down to the
17f0ded5f3SAzat Khuzhin#    instantiated factory objects.
18f0ded5f3SAzat Khuzhin# 2) move the globals into a class that manages execution, including the
19f0ded5f3SAzat Khuzhin#    progress outputs that go to stderr at the moment.
20f0ded5f3SAzat Khuzhin# 3) emit other languages.
21f0ded5f3SAzat Khuzhin
22f0ded5f3SAzat Khuzhinimport argparse
23949cbd12SNiels Provosimport re
24f0ded5f3SAzat Khuzhinimport sys
25949cbd12SNiels Provos
26949cbd12SNiels Provos_NAME = "event_rpcgen.py"
27949cbd12SNiels Provos_VERSION = "0.1"
28949cbd12SNiels Provos
29949cbd12SNiels Provos# Globals
30f0ded5f3SAzat KhuzhinLINE_COUNT = 0
31949cbd12SNiels Provos
32f0ded5f3SAzat KhuzhinCPPCOMMENT_RE = re.compile(r"\/\/.*$")
33f0ded5f3SAzat KhuzhinNONIDENT_RE = re.compile(r"\W")
34f0ded5f3SAzat KhuzhinPREPROCESSOR_DEF_RE = re.compile(r"^#define")
35f0ded5f3SAzat KhuzhinSTRUCT_REF_RE = re.compile(r"^struct\[(?P<name>[a-zA-Z_][a-zA-Z0-9_]*)\]$")
36f0ded5f3SAzat KhuzhinSTRUCT_DEF_RE = re.compile(r"^struct +[a-zA-Z_][a-zA-Z0-9_]* *{$")
37f0ded5f3SAzat KhuzhinWHITESPACE_RE = re.compile(r"\s+")
386469598eSNiels Provos
39f0ded5f3SAzat KhuzhinHEADER_DIRECT = []
40f0ded5f3SAzat KhuzhinCPP_DIRECT = []
41949cbd12SNiels Provos
42f0ded5f3SAzat KhuzhinQUIETLY = False
43f0ded5f3SAzat Khuzhin
44aa59c1e9SNick Mathewson
45aa59c1e9SNick Mathewsondef declare(s):
46aa59c1e9SNick Mathewson    if not QUIETLY:
47532a8cc3SKiyoshi Aman        print(s)
48aa59c1e9SNick Mathewson
49f0ded5f3SAzat Khuzhin
5068725dc8SNiels Provosdef TranslateList(mylist, mydict):
51532a8cc3SKiyoshi Aman    return [x % mydict for x in mylist]
5268725dc8SNiels Provos
53f0ded5f3SAzat Khuzhin
5437d3e16cSNiels Provosclass RpcGenError(Exception):
55f0ded5f3SAzat Khuzhin    """An Exception class for parse errors."""
56f0ded5f3SAzat Khuzhin
57f0ded5f3SAzat Khuzhin    def __init__(self, why): # pylint: disable=super-init-not-called
5837d3e16cSNiels Provos        self.why = why
59f0ded5f3SAzat Khuzhin
6037d3e16cSNiels Provos    def __str__(self):
6137d3e16cSNiels Provos        return str(self.why)
6237d3e16cSNiels Provos
63f0ded5f3SAzat Khuzhin
64949cbd12SNiels Provos# Holds everything that makes a struct
65*48e04887SEnji Cooperclass Struct(object):
66949cbd12SNiels Provos    def __init__(self, name):
67949cbd12SNiels Provos        self._name = name
68949cbd12SNiels Provos        self._entries = []
69949cbd12SNiels Provos        self._tags = {}
70f0ded5f3SAzat Khuzhin        declare("  Created struct: %s" % name)
71949cbd12SNiels Provos
72949cbd12SNiels Provos    def AddEntry(self, entry):
73532a8cc3SKiyoshi Aman        if entry.Tag() in self._tags:
7437d3e16cSNiels Provos            raise RpcGenError(
7537d3e16cSNiels Provos                'Entry "%s" duplicates tag number %d from "%s" '
76f0ded5f3SAzat Khuzhin                "around line %d"
77f0ded5f3SAzat Khuzhin                % (entry.Name(), entry.Tag(), self._tags[entry.Tag()], LINE_COUNT)
78f0ded5f3SAzat Khuzhin            )
79949cbd12SNiels Provos        self._entries.append(entry)
80949cbd12SNiels Provos        self._tags[entry.Tag()] = entry.Name()
81f0ded5f3SAzat Khuzhin        declare("    Added entry: %s" % entry.Name())
82949cbd12SNiels Provos
83949cbd12SNiels Provos    def Name(self):
84949cbd12SNiels Provos        return self._name
85949cbd12SNiels Provos
86949cbd12SNiels Provos    def EntryTagName(self, entry):
87b4ab56dcSNiels Provos        """Creates the name inside an enumeration for distinguishing data
88b4ab56dcSNiels Provos        types."""
89949cbd12SNiels Provos        name = "%s_%s" % (self._name, entry.Name())
90949cbd12SNiels Provos        return name.upper()
91949cbd12SNiels Provos
92f0ded5f3SAzat Khuzhin    @staticmethod
93f0ded5f3SAzat Khuzhin    def PrintIndented(filep, ident, code):
94812d2fd8SNiels Provos        """Takes an array, add indentation to each entry and prints it."""
95812d2fd8SNiels Provos        for entry in code:
96f0ded5f3SAzat Khuzhin            filep.write("%s%s\n" % (ident, entry))
97f0ded5f3SAzat Khuzhin
98812d2fd8SNiels Provos
99a7e39551SNiels Provosclass StructCCode(Struct):
100a7e39551SNiels Provos    """ Knows how to generate C code for a struct """
101a7e39551SNiels Provos
102a7e39551SNiels Provos    def __init__(self, name):
103a7e39551SNiels Provos        Struct.__init__(self, name)
104a7e39551SNiels Provos
105f0ded5f3SAzat Khuzhin    def PrintTags(self, filep):
106b4ab56dcSNiels Provos        """Prints the tag definitions for a structure."""
107f0ded5f3SAzat Khuzhin        filep.write("/* Tag definition for %s */\n" % self._name)
108f0ded5f3SAzat Khuzhin        filep.write("enum %s_ {\n" % self._name.lower())
109949cbd12SNiels Provos        for entry in self._entries:
110f0ded5f3SAzat Khuzhin            filep.write("  %s=%d,\n" % (self.EntryTagName(entry), entry.Tag()))
111f0ded5f3SAzat Khuzhin        filep.write("  %s_MAX_TAGS\n" % (self._name.upper()))
112f0ded5f3SAzat Khuzhin        filep.write("};\n\n")
113949cbd12SNiels Provos
114f0ded5f3SAzat Khuzhin    def PrintForwardDeclaration(self, filep):
115f0ded5f3SAzat Khuzhin        filep.write("struct %s;\n" % self._name)
116949cbd12SNiels Provos
117f0ded5f3SAzat Khuzhin    def PrintDeclaration(self, filep):
118f0ded5f3SAzat Khuzhin        filep.write("/* Structure declaration for %s */\n" % self._name)
119f0ded5f3SAzat Khuzhin        filep.write("struct %s_access_ {\n" % self._name)
120949cbd12SNiels Provos        for entry in self._entries:
121f0ded5f3SAzat Khuzhin            dcl = entry.AssignDeclaration("(*%s_assign)" % entry.Name())
122f0ded5f3SAzat Khuzhin            dcl.extend(entry.GetDeclaration("(*%s_get)" % entry.Name()))
123b4ab56dcSNiels Provos            if entry.Array():
124f0ded5f3SAzat Khuzhin                dcl.extend(entry.AddDeclaration("(*%s_add)" % entry.Name()))
125f0ded5f3SAzat Khuzhin            self.PrintIndented(filep, "  ", dcl)
126f0ded5f3SAzat Khuzhin        filep.write("};\n\n")
1273b345f3eSNiels Provos
128f0ded5f3SAzat Khuzhin        filep.write("struct %s {\n" % self._name)
129f0ded5f3SAzat Khuzhin        filep.write("  struct %s_access_ *base;\n\n" % self._name)
1303b345f3eSNiels Provos        for entry in self._entries:
1313b345f3eSNiels Provos            dcl = entry.Declaration()
132f0ded5f3SAzat Khuzhin            self.PrintIndented(filep, "  ", dcl)
133f0ded5f3SAzat Khuzhin        filep.write("\n")
134949cbd12SNiels Provos        for entry in self._entries:
135f0ded5f3SAzat Khuzhin            filep.write("  ev_uint8_t %s_set;\n" % entry.Name())
136f0ded5f3SAzat Khuzhin        filep.write("};\n\n")
137949cbd12SNiels Provos
138f0ded5f3SAzat Khuzhin        filep.write(
139f0ded5f3SAzat Khuzhin            """struct %(name)s *%(name)s_new(void);
140755fbf16SShuo Chenstruct %(name)s *%(name)s_new_with_arg(void *);
1413c1a6a68SNiels Provosvoid %(name)s_free(struct %(name)s *);
1423c1a6a68SNiels Provosvoid %(name)s_clear(struct %(name)s *);
1433c1a6a68SNiels Provosvoid %(name)s_marshal(struct evbuffer *, const struct %(name)s *);
1443c1a6a68SNiels Provosint %(name)s_unmarshal(struct %(name)s *, struct evbuffer *);
1453c1a6a68SNiels Provosint %(name)s_complete(struct %(name)s *);
14611230f7eSNick Mathewsonvoid evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t,
1473c1a6a68SNiels Provos    const struct %(name)s *);
14811230f7eSNick Mathewsonint evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
149f0ded5f3SAzat Khuzhin    struct %(name)s *);\n"""
150f0ded5f3SAzat Khuzhin            % {"name": self._name}
151f0ded5f3SAzat Khuzhin        )
152949cbd12SNiels Provos
153949cbd12SNiels Provos        # Write a setting function of every variable
154949cbd12SNiels Provos        for entry in self._entries:
155f0ded5f3SAzat Khuzhin            self.PrintIndented(
156f0ded5f3SAzat Khuzhin                filep, "", entry.AssignDeclaration(entry.AssignFuncName())
157f0ded5f3SAzat Khuzhin            )
158f0ded5f3SAzat Khuzhin            self.PrintIndented(filep, "", entry.GetDeclaration(entry.GetFuncName()))
159b4ab56dcSNiels Provos            if entry.Array():
160f0ded5f3SAzat Khuzhin                self.PrintIndented(filep, "", entry.AddDeclaration(entry.AddFuncName()))
161949cbd12SNiels Provos
162f0ded5f3SAzat Khuzhin        filep.write("/* --- %s done --- */\n\n" % self._name)
163949cbd12SNiels Provos
164f0ded5f3SAzat Khuzhin    def PrintCode(self, filep):
165f0ded5f3SAzat Khuzhin        filep.write(
166f0ded5f3SAzat Khuzhin            """/*
167f0ded5f3SAzat Khuzhin * Implementation of %s
168f0ded5f3SAzat Khuzhin */
169f0ded5f3SAzat Khuzhin"""
170f0ded5f3SAzat Khuzhin            % (self._name)
171f0ded5f3SAzat Khuzhin        )
172949cbd12SNiels Provos
173f0ded5f3SAzat Khuzhin        filep.write(
174f0ded5f3SAzat Khuzhin            """
175f0ded5f3SAzat Khuzhinstatic struct %(name)s_access_ %(name)s_base__ = {
176f0ded5f3SAzat Khuzhin"""
177f0ded5f3SAzat Khuzhin            % {"name": self._name}
178f0ded5f3SAzat Khuzhin        )
1793b345f3eSNiels Provos        for entry in self._entries:
180f0ded5f3SAzat Khuzhin            self.PrintIndented(filep, "  ", entry.CodeBase())
181f0ded5f3SAzat Khuzhin        filep.write("};\n\n")
1823b345f3eSNiels Provos
183949cbd12SNiels Provos        # Creation
184f0ded5f3SAzat Khuzhin        filep.write(
185f0ded5f3SAzat Khuzhin            """struct %(name)s *
186f0ded5f3SAzat Khuzhin%(name)s_new(void)
187f0ded5f3SAzat Khuzhin{
188f0ded5f3SAzat Khuzhin  return %(name)s_new_with_arg(NULL);
189f0ded5f3SAzat Khuzhin}
190f0ded5f3SAzat Khuzhin
191f0ded5f3SAzat Khuzhinstruct %(name)s *
192f0ded5f3SAzat Khuzhin%(name)s_new_with_arg(void *unused)
193f0ded5f3SAzat Khuzhin{
194f0ded5f3SAzat Khuzhin  struct %(name)s *tmp;
195f0ded5f3SAzat Khuzhin  if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {
196f0ded5f3SAzat Khuzhin    event_warn("%%s: malloc", __func__);
197f0ded5f3SAzat Khuzhin    return (NULL);
198f0ded5f3SAzat Khuzhin  }
199f0ded5f3SAzat Khuzhin  tmp->base = &%(name)s_base__;
200f0ded5f3SAzat Khuzhin
201f0ded5f3SAzat Khuzhin"""
202f0ded5f3SAzat Khuzhin            % {"name": self._name}
203f0ded5f3SAzat Khuzhin        )
2043c1a6a68SNiels Provos
205949cbd12SNiels Provos        for entry in self._entries:
206f0ded5f3SAzat Khuzhin            self.PrintIndented(filep, "  ", entry.CodeInitialize("tmp"))
207f0ded5f3SAzat Khuzhin            filep.write("  tmp->%s_set = 0;\n\n" % entry.Name())
208949cbd12SNiels Provos
209f0ded5f3SAzat Khuzhin        filep.write(
210f0ded5f3SAzat Khuzhin            """  return (tmp);
211f0ded5f3SAzat Khuzhin}
212f0ded5f3SAzat Khuzhin
213f0ded5f3SAzat Khuzhin"""
214f0ded5f3SAzat Khuzhin        )
215949cbd12SNiels Provos
216b4ab56dcSNiels Provos        # Adding
217b4ab56dcSNiels Provos        for entry in self._entries:
218b4ab56dcSNiels Provos            if entry.Array():
219f0ded5f3SAzat Khuzhin                self.PrintIndented(filep, "", entry.CodeAdd())
220f0ded5f3SAzat Khuzhin            filep.write("\n")
221b4ab56dcSNiels Provos
222949cbd12SNiels Provos        # Assigning
223949cbd12SNiels Provos        for entry in self._entries:
224f0ded5f3SAzat Khuzhin            self.PrintIndented(filep, "", entry.CodeAssign())
225f0ded5f3SAzat Khuzhin            filep.write("\n")
226949cbd12SNiels Provos
227949cbd12SNiels Provos        # Getting
228949cbd12SNiels Provos        for entry in self._entries:
229f0ded5f3SAzat Khuzhin            self.PrintIndented(filep, "", entry.CodeGet())
230f0ded5f3SAzat Khuzhin            filep.write("\n")
231949cbd12SNiels Provos
232949cbd12SNiels Provos        # Clearing
233f0ded5f3SAzat Khuzhin        filep.write(
234f0ded5f3SAzat Khuzhin            """void
235f0ded5f3SAzat Khuzhin%(name)s_clear(struct %(name)s *tmp)
236f0ded5f3SAzat Khuzhin{
237f0ded5f3SAzat Khuzhin"""
238f0ded5f3SAzat Khuzhin            % {"name": self._name}
239f0ded5f3SAzat Khuzhin        )
240949cbd12SNiels Provos        for entry in self._entries:
241f0ded5f3SAzat Khuzhin            self.PrintIndented(filep, "  ", entry.CodeClear("tmp"))
242949cbd12SNiels Provos
243f0ded5f3SAzat Khuzhin        filep.write("}\n\n")
244949cbd12SNiels Provos
245949cbd12SNiels Provos        # Freeing
246f0ded5f3SAzat Khuzhin        filep.write(
247f0ded5f3SAzat Khuzhin            """void
248f0ded5f3SAzat Khuzhin%(name)s_free(struct %(name)s *tmp)
249f0ded5f3SAzat Khuzhin{
250f0ded5f3SAzat Khuzhin"""
251f0ded5f3SAzat Khuzhin            % {"name": self._name}
252f0ded5f3SAzat Khuzhin        )
2533c1a6a68SNiels Provos
254949cbd12SNiels Provos        for entry in self._entries:
255f0ded5f3SAzat Khuzhin            self.PrintIndented(filep, "  ", entry.CodeFree("tmp"))
256949cbd12SNiels Provos
257f0ded5f3SAzat Khuzhin        filep.write(
258f0ded5f3SAzat Khuzhin            """  free(tmp);
259f0ded5f3SAzat Khuzhin}
260f0ded5f3SAzat Khuzhin
261f0ded5f3SAzat Khuzhin"""
262f0ded5f3SAzat Khuzhin        )
263949cbd12SNiels Provos
264949cbd12SNiels Provos        # Marshaling
265f0ded5f3SAzat Khuzhin        filep.write(
266f0ded5f3SAzat Khuzhin            """void
267f0ded5f3SAzat Khuzhin%(name)s_marshal(struct evbuffer *evbuf, const struct %(name)s *tmp) {
268f0ded5f3SAzat Khuzhin"""
269f0ded5f3SAzat Khuzhin            % {"name": self._name}
270f0ded5f3SAzat Khuzhin        )
271949cbd12SNiels Provos        for entry in self._entries:
272f0ded5f3SAzat Khuzhin            indent = "  "
273949cbd12SNiels Provos            # Optional entries do not have to be set
274949cbd12SNiels Provos            if entry.Optional():
275f0ded5f3SAzat Khuzhin                indent += "  "
276f0ded5f3SAzat Khuzhin                filep.write("  if (tmp->%s_set) {\n" % entry.Name())
27768725dc8SNiels Provos            self.PrintIndented(
278f0ded5f3SAzat Khuzhin                filep,
279f0ded5f3SAzat Khuzhin                indent,
280f0ded5f3SAzat Khuzhin                entry.CodeMarshal(
281f0ded5f3SAzat Khuzhin                    "evbuf",
282f0ded5f3SAzat Khuzhin                    self.EntryTagName(entry),
283f0ded5f3SAzat Khuzhin                    entry.GetVarName("tmp"),
284f0ded5f3SAzat Khuzhin                    entry.GetVarLen("tmp"),
285f0ded5f3SAzat Khuzhin                ),
286f0ded5f3SAzat Khuzhin            )
287949cbd12SNiels Provos            if entry.Optional():
288f0ded5f3SAzat Khuzhin                filep.write("  }\n")
289949cbd12SNiels Provos
290f0ded5f3SAzat Khuzhin        filep.write("}\n\n")
291949cbd12SNiels Provos
292949cbd12SNiels Provos        # Unmarshaling
293f0ded5f3SAzat Khuzhin        filep.write(
294f0ded5f3SAzat Khuzhin            """int
295f0ded5f3SAzat Khuzhin%(name)s_unmarshal(struct %(name)s *tmp, struct evbuffer *evbuf)
296f0ded5f3SAzat Khuzhin{
297f0ded5f3SAzat Khuzhin  ev_uint32_t tag;
298f0ded5f3SAzat Khuzhin  while (evbuffer_get_length(evbuf) > 0) {
299f0ded5f3SAzat Khuzhin    if (evtag_peek(evbuf, &tag) == -1)
300f0ded5f3SAzat Khuzhin      return (-1);
301f0ded5f3SAzat Khuzhin    switch (tag) {
302f0ded5f3SAzat Khuzhin
303f0ded5f3SAzat Khuzhin"""
304f0ded5f3SAzat Khuzhin            % {"name": self._name}
305f0ded5f3SAzat Khuzhin        )
306949cbd12SNiels Provos        for entry in self._entries:
307f0ded5f3SAzat Khuzhin            filep.write("      case %s:\n" % (self.EntryTagName(entry)))
308b4ab56dcSNiels Provos            if not entry.Array():
309f0ded5f3SAzat Khuzhin                filep.write(
310f0ded5f3SAzat Khuzhin                    """        if (tmp->%s_set)
311f0ded5f3SAzat Khuzhin          return (-1);
312f0ded5f3SAzat Khuzhin"""
313f0ded5f3SAzat Khuzhin                    % (entry.Name())
314f0ded5f3SAzat Khuzhin                )
315b4ab56dcSNiels Provos
31668725dc8SNiels Provos            self.PrintIndented(
317f0ded5f3SAzat Khuzhin                filep,
318f0ded5f3SAzat Khuzhin                "        ",
319f0ded5f3SAzat Khuzhin                entry.CodeUnmarshal(
320f0ded5f3SAzat Khuzhin                    "evbuf",
32168725dc8SNiels Provos                    self.EntryTagName(entry),
322f0ded5f3SAzat Khuzhin                    entry.GetVarName("tmp"),
323f0ded5f3SAzat Khuzhin                    entry.GetVarLen("tmp"),
324f0ded5f3SAzat Khuzhin                ),
325f0ded5f3SAzat Khuzhin            )
326949cbd12SNiels Provos
327f0ded5f3SAzat Khuzhin            filep.write(
328f0ded5f3SAzat Khuzhin                """        tmp->%s_set = 1;
329f0ded5f3SAzat Khuzhin        break;
330f0ded5f3SAzat Khuzhin"""
331f0ded5f3SAzat Khuzhin                % (entry.Name())
332f0ded5f3SAzat Khuzhin            )
333f0ded5f3SAzat Khuzhin        filep.write(
334f0ded5f3SAzat Khuzhin            """      default:
335f0ded5f3SAzat Khuzhin        return -1;
336f0ded5f3SAzat Khuzhin    }
337f0ded5f3SAzat Khuzhin  }
338f0ded5f3SAzat Khuzhin
339f0ded5f3SAzat Khuzhin"""
340f0ded5f3SAzat Khuzhin        )
341949cbd12SNiels Provos        # Check if it was decoded completely
342f0ded5f3SAzat Khuzhin        filep.write(
343f0ded5f3SAzat Khuzhin            """  if (%(name)s_complete(tmp) == -1)
344f0ded5f3SAzat Khuzhin    return (-1);
345f0ded5f3SAzat Khuzhin  return (0);
346f0ded5f3SAzat Khuzhin}
347f0ded5f3SAzat Khuzhin"""
348f0ded5f3SAzat Khuzhin            % {"name": self._name}
349f0ded5f3SAzat Khuzhin        )
350949cbd12SNiels Provos
351949cbd12SNiels Provos        # Checking if a structure has all the required data
352f0ded5f3SAzat Khuzhin        filep.write(
353f0ded5f3SAzat Khuzhin            """
354f0ded5f3SAzat Khuzhinint
355f0ded5f3SAzat Khuzhin%(name)s_complete(struct %(name)s *msg)
356f0ded5f3SAzat Khuzhin{
357f0ded5f3SAzat Khuzhin"""
358f0ded5f3SAzat Khuzhin            % {"name": self._name}
359f0ded5f3SAzat Khuzhin        )
360949cbd12SNiels Provos        for entry in self._entries:
36168725dc8SNiels Provos            if not entry.Optional():
36268725dc8SNiels Provos                code = [
363f0ded5f3SAzat Khuzhin                    """if (!msg->%(name)s_set)
364f0ded5f3SAzat Khuzhin    return (-1);"""
365f0ded5f3SAzat Khuzhin                ]
36668725dc8SNiels Provos                code = TranslateList(code, entry.GetTranslation())
367f0ded5f3SAzat Khuzhin                self.PrintIndented(filep, "  ", code)
36868725dc8SNiels Provos
36968725dc8SNiels Provos            self.PrintIndented(
370f0ded5f3SAzat Khuzhin                filep, "  ", entry.CodeComplete("msg", entry.GetVarName("msg"))
371f0ded5f3SAzat Khuzhin            )
372f0ded5f3SAzat Khuzhin        filep.write(
373f0ded5f3SAzat Khuzhin            """  return (0);
374f0ded5f3SAzat Khuzhin}
375f0ded5f3SAzat Khuzhin"""
376f0ded5f3SAzat Khuzhin        )
377949cbd12SNiels Provos
378949cbd12SNiels Provos        # Complete message unmarshaling
379f0ded5f3SAzat Khuzhin        filep.write(
380f0ded5f3SAzat Khuzhin            """
381f0ded5f3SAzat Khuzhinint
382f0ded5f3SAzat Khuzhinevtag_unmarshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t need_tag,
383f0ded5f3SAzat Khuzhin  struct %(name)s *msg)
384f0ded5f3SAzat Khuzhin{
385f0ded5f3SAzat Khuzhin  ev_uint32_t tag;
386f0ded5f3SAzat Khuzhin  int res = -1;
387f0ded5f3SAzat Khuzhin
388f0ded5f3SAzat Khuzhin  struct evbuffer *tmp = evbuffer_new();
389f0ded5f3SAzat Khuzhin
390f0ded5f3SAzat Khuzhin  if (evtag_unmarshal(evbuf, &tag, tmp) == -1 || tag != need_tag)
391f0ded5f3SAzat Khuzhin    goto error;
392f0ded5f3SAzat Khuzhin
393f0ded5f3SAzat Khuzhin  if (%(name)s_unmarshal(msg, tmp) == -1)
394f0ded5f3SAzat Khuzhin    goto error;
395f0ded5f3SAzat Khuzhin
396f0ded5f3SAzat Khuzhin  res = 0;
397f0ded5f3SAzat Khuzhin
398f0ded5f3SAzat Khuzhin error:
399f0ded5f3SAzat Khuzhin  evbuffer_free(tmp);
400f0ded5f3SAzat Khuzhin  return (res);
401f0ded5f3SAzat Khuzhin}
402f0ded5f3SAzat Khuzhin"""
403f0ded5f3SAzat Khuzhin            % {"name": self._name}
404f0ded5f3SAzat Khuzhin        )
405949cbd12SNiels Provos
406949cbd12SNiels Provos        # Complete message marshaling
407f0ded5f3SAzat Khuzhin        filep.write(
408f0ded5f3SAzat Khuzhin            """
409f0ded5f3SAzat Khuzhinvoid
410f0ded5f3SAzat Khuzhinevtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag,
411f0ded5f3SAzat Khuzhin    const struct %(name)s *msg)
412f0ded5f3SAzat Khuzhin{
413f0ded5f3SAzat Khuzhin  struct evbuffer *buf_ = evbuffer_new();
414f0ded5f3SAzat Khuzhin  assert(buf_ != NULL);
415f0ded5f3SAzat Khuzhin  %(name)s_marshal(buf_, msg);
416f0ded5f3SAzat Khuzhin  evtag_marshal_buffer(evbuf, tag, buf_);
417f0ded5f3SAzat Khuzhin  evbuffer_free(buf_);
418f0ded5f3SAzat Khuzhin}
419f0ded5f3SAzat Khuzhin
420f0ded5f3SAzat Khuzhin"""
421f0ded5f3SAzat Khuzhin            % {"name": self._name}
422f0ded5f3SAzat Khuzhin        )
423f0ded5f3SAzat Khuzhin
424949cbd12SNiels Provos
425*48e04887SEnji Cooperclass Entry(object):
426f0ded5f3SAzat Khuzhin    def __init__(self, ent_type, name, tag):
427f0ded5f3SAzat Khuzhin        self._type = ent_type
428949cbd12SNiels Provos        self._name = name
429949cbd12SNiels Provos        self._tag = int(tag)
430f0ded5f3SAzat Khuzhin        self._ctype = ent_type
431f0ded5f3SAzat Khuzhin        self._optional = False
432f0ded5f3SAzat Khuzhin        self._can_be_array = False
433f0ded5f3SAzat Khuzhin        self._array = False
434949cbd12SNiels Provos        self._line_count = -1
435949cbd12SNiels Provos        self._struct = None
4363c1a6a68SNiels Provos        self._refname = None
4373c1a6a68SNiels Provos
43868725dc8SNiels Provos        self._optpointer = True
43968725dc8SNiels Provos        self._optaddarg = True
44068725dc8SNiels Provos
441f0ded5f3SAzat Khuzhin    @staticmethod
442f0ded5f3SAzat Khuzhin    def GetInitializer():
443f0ded5f3SAzat Khuzhin        raise NotImplementedError("Entry does not provide an initializer")
44468725dc8SNiels Provos
445949cbd12SNiels Provos    def SetStruct(self, struct):
446949cbd12SNiels Provos        self._struct = struct
447949cbd12SNiels Provos
448949cbd12SNiels Provos    def LineCount(self):
449949cbd12SNiels Provos        assert self._line_count != -1
450949cbd12SNiels Provos        return self._line_count
451949cbd12SNiels Provos
452949cbd12SNiels Provos    def SetLineCount(self, number):
453949cbd12SNiels Provos        self._line_count = number
454949cbd12SNiels Provos
455b4ab56dcSNiels Provos    def Array(self):
456b4ab56dcSNiels Provos        return self._array
457b4ab56dcSNiels Provos
458949cbd12SNiels Provos    def Optional(self):
459949cbd12SNiels Provos        return self._optional
460949cbd12SNiels Provos
461949cbd12SNiels Provos    def Tag(self):
462949cbd12SNiels Provos        return self._tag
463949cbd12SNiels Provos
464949cbd12SNiels Provos    def Name(self):
465949cbd12SNiels Provos        return self._name
466949cbd12SNiels Provos
467949cbd12SNiels Provos    def Type(self):
468949cbd12SNiels Provos        return self._type
469949cbd12SNiels Provos
470f0ded5f3SAzat Khuzhin    def MakeArray(self):
471f0ded5f3SAzat Khuzhin        self._array = True
472949cbd12SNiels Provos
473949cbd12SNiels Provos    def MakeOptional(self):
474f0ded5f3SAzat Khuzhin        self._optional = True
475949cbd12SNiels Provos
476a7e39551SNiels Provos    def Verify(self):
477a7e39551SNiels Provos        if self.Array() and not self._can_be_array:
47837d3e16cSNiels Provos            raise RpcGenError(
479a7e39551SNiels Provos                'Entry "%s" cannot be created as an array '
480f0ded5f3SAzat Khuzhin                "around line %d" % (self._name, self.LineCount())
481f0ded5f3SAzat Khuzhin            )
482a7e39551SNiels Provos        if not self._struct:
48337d3e16cSNiels Provos            raise RpcGenError(
484a7e39551SNiels Provos                'Entry "%s" does not know which struct it belongs to '
485f0ded5f3SAzat Khuzhin                "around line %d" % (self._name, self.LineCount())
486f0ded5f3SAzat Khuzhin            )
487a7e39551SNiels Provos        if self._optional and self._array:
48837d3e16cSNiels Provos            raise RpcGenError(
48937d3e16cSNiels Provos                'Entry "%s" has illegal combination of optional and array '
490f0ded5f3SAzat Khuzhin                "around line %d" % (self._name, self.LineCount())
491f0ded5f3SAzat Khuzhin            )
492a7e39551SNiels Provos
493f0ded5f3SAzat Khuzhin    def GetTranslation(self, extradict=None):
494f0ded5f3SAzat Khuzhin        if extradict is None:
495f0ded5f3SAzat Khuzhin            extradict = {}
496a7e39551SNiels Provos        mapping = {
497a7e39551SNiels Provos            "parent_name": self._struct.Name(),
498a7e39551SNiels Provos            "name": self._name,
499a7e39551SNiels Provos            "ctype": self._ctype,
500a7e39551SNiels Provos            "refname": self._refname,
501a7e39551SNiels Provos            "optpointer": self._optpointer and "*" or "",
502a7e39551SNiels Provos            "optreference": self._optpointer and "&" or "",
503f0ded5f3SAzat Khuzhin            "optaddarg": self._optaddarg and ", const %s value" % self._ctype or "",
504a7e39551SNiels Provos        }
505532a8cc3SKiyoshi Aman        for (k, v) in list(extradict.items()):
506a7e39551SNiels Provos            mapping[k] = v
507a7e39551SNiels Provos
508a7e39551SNiels Provos        return mapping
509a7e39551SNiels Provos
51068725dc8SNiels Provos    def GetVarName(self, var):
511f0ded5f3SAzat Khuzhin        return "%(var)s->%(name)s_data" % self.GetTranslation({"var": var})
51268725dc8SNiels Provos
513f0ded5f3SAzat Khuzhin    def GetVarLen(self, _var):
514f0ded5f3SAzat Khuzhin        return "sizeof(%s)" % self._ctype
51568725dc8SNiels Provos
516949cbd12SNiels Provos    def GetFuncName(self):
517f0ded5f3SAzat Khuzhin        return "%s_%s_get" % (self._struct.Name(), self._name)
518949cbd12SNiels Provos
519949cbd12SNiels Provos    def GetDeclaration(self, funcname):
520f0ded5f3SAzat Khuzhin        code = [
521f0ded5f3SAzat Khuzhin            "int %s(struct %s *, %s *);" % (funcname, self._struct.Name(), self._ctype)
522f0ded5f3SAzat Khuzhin        ]
523949cbd12SNiels Provos        return code
524949cbd12SNiels Provos
525949cbd12SNiels Provos    def CodeGet(self):
526f0ded5f3SAzat Khuzhin        code = """int
527f0ded5f3SAzat Khuzhin%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, %(ctype)s *value)
528f0ded5f3SAzat Khuzhin{
529f0ded5f3SAzat Khuzhin  if (msg->%(name)s_set != 1)
530f0ded5f3SAzat Khuzhin    return (-1);
531f0ded5f3SAzat Khuzhin  *value = msg->%(name)s_data;
532f0ded5f3SAzat Khuzhin  return (0);
533f0ded5f3SAzat Khuzhin}"""
5343c1a6a68SNiels Provos        code = code % self.GetTranslation()
535f0ded5f3SAzat Khuzhin        return code.split("\n")
536949cbd12SNiels Provos
537949cbd12SNiels Provos    def AssignFuncName(self):
538f0ded5f3SAzat Khuzhin        return "%s_%s_assign" % (self._struct.Name(), self._name)
539949cbd12SNiels Provos
540b4ab56dcSNiels Provos    def AddFuncName(self):
541f0ded5f3SAzat Khuzhin        return "%s_%s_add" % (self._struct.Name(), self._name)
542b4ab56dcSNiels Provos
543949cbd12SNiels Provos    def AssignDeclaration(self, funcname):
544f0ded5f3SAzat Khuzhin        code = [
545f0ded5f3SAzat Khuzhin            "int %s(struct %s *, const %s);"
546f0ded5f3SAzat Khuzhin            % (funcname, self._struct.Name(), self._ctype)
547f0ded5f3SAzat Khuzhin        ]
548949cbd12SNiels Provos        return code
549949cbd12SNiels Provos
550949cbd12SNiels Provos    def CodeAssign(self):
551f0ded5f3SAzat Khuzhin        code = [
552f0ded5f3SAzat Khuzhin            "int",
553f0ded5f3SAzat Khuzhin            "%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,"
554f0ded5f3SAzat Khuzhin            " const %(ctype)s value)",
555f0ded5f3SAzat Khuzhin            "{",
556f0ded5f3SAzat Khuzhin            "  msg->%(name)s_set = 1;",
557f0ded5f3SAzat Khuzhin            "  msg->%(name)s_data = value;",
558f0ded5f3SAzat Khuzhin            "  return (0);",
559f0ded5f3SAzat Khuzhin            "}",
560f0ded5f3SAzat Khuzhin        ]
561f0ded5f3SAzat Khuzhin        code = "\n".join(code)
5623c1a6a68SNiels Provos        code = code % self.GetTranslation()
563f0ded5f3SAzat Khuzhin        return code.split("\n")
564949cbd12SNiels Provos
565949cbd12SNiels Provos    def CodeClear(self, structname):
566f0ded5f3SAzat Khuzhin        code = ["%s->%s_set = 0;" % (structname, self.Name())]
567949cbd12SNiels Provos
568949cbd12SNiels Provos        return code
569949cbd12SNiels Provos
570f0ded5f3SAzat Khuzhin    @staticmethod
571f0ded5f3SAzat Khuzhin    def CodeComplete(_structname, _var_name):
572949cbd12SNiels Provos        return []
573949cbd12SNiels Provos
574f0ded5f3SAzat Khuzhin    @staticmethod
575f0ded5f3SAzat Khuzhin    def CodeFree(_name):
576949cbd12SNiels Provos        return []
577949cbd12SNiels Provos
5783b345f3eSNiels Provos    def CodeBase(self):
579f0ded5f3SAzat Khuzhin        code = ["%(parent_name)s_%(name)s_assign,", "%(parent_name)s_%(name)s_get,"]
580b4ab56dcSNiels Provos        if self.Array():
581f0ded5f3SAzat Khuzhin            code.append("%(parent_name)s_%(name)s_add,")
5823c1a6a68SNiels Provos
583f0ded5f3SAzat Khuzhin        code = "\n".join(code)
5843b345f3eSNiels Provos        code = code % self.GetTranslation()
585f0ded5f3SAzat Khuzhin        return code.split("\n")
586f0ded5f3SAzat Khuzhin
587949cbd12SNiels Provos
588949cbd12SNiels Provosclass EntryBytes(Entry):
589f0ded5f3SAzat Khuzhin    def __init__(self, ent_type, name, tag, length):
590949cbd12SNiels Provos        # Init base class
591f0ded5f3SAzat Khuzhin        super(EntryBytes, self).__init__(ent_type, name, tag)
592949cbd12SNiels Provos
593949cbd12SNiels Provos        self._length = length
594f0ded5f3SAzat Khuzhin        self._ctype = "ev_uint8_t"
59568725dc8SNiels Provos
596f0ded5f3SAzat Khuzhin    @staticmethod
597f0ded5f3SAzat Khuzhin    def GetInitializer():
59868725dc8SNiels Provos        return "NULL"
59968725dc8SNiels Provos
600f0ded5f3SAzat Khuzhin    def GetVarLen(self, _var):
601f0ded5f3SAzat Khuzhin        return "(%s)" % self._length
60268725dc8SNiels Provos
603f0ded5f3SAzat Khuzhin    @staticmethod
604f0ded5f3SAzat Khuzhin    def CodeArrayAdd(varname, _value):
60568725dc8SNiels Provos        # XXX: copy here
606f0ded5f3SAzat Khuzhin        return ["%(varname)s = NULL;" % {"varname": varname}]
607949cbd12SNiels Provos
608949cbd12SNiels Provos    def GetDeclaration(self, funcname):
609f0ded5f3SAzat Khuzhin        code = [
610f0ded5f3SAzat Khuzhin            "int %s(struct %s *, %s **);" % (funcname, self._struct.Name(), self._ctype)
611f0ded5f3SAzat Khuzhin        ]
612949cbd12SNiels Provos        return code
613949cbd12SNiels Provos
614949cbd12SNiels Provos    def AssignDeclaration(self, funcname):
615f0ded5f3SAzat Khuzhin        code = [
616f0ded5f3SAzat Khuzhin            "int %s(struct %s *, const %s *);"
617f0ded5f3SAzat Khuzhin            % (funcname, self._struct.Name(), self._ctype)
618f0ded5f3SAzat Khuzhin        ]
619949cbd12SNiels Provos        return code
620949cbd12SNiels Provos
621949cbd12SNiels Provos    def Declaration(self):
622f0ded5f3SAzat Khuzhin        dcl = ["ev_uint8_t %s_data[%s];" % (self._name, self._length)]
623949cbd12SNiels Provos
624949cbd12SNiels Provos        return dcl
625949cbd12SNiels Provos
626949cbd12SNiels Provos    def CodeGet(self):
627949cbd12SNiels Provos        name = self._name
628f0ded5f3SAzat Khuzhin        code = [
629f0ded5f3SAzat Khuzhin            "int",
630f0ded5f3SAzat Khuzhin            "%s_%s_get(struct %s *msg, %s **value)"
631f0ded5f3SAzat Khuzhin            % (self._struct.Name(), name, self._struct.Name(), self._ctype),
632f0ded5f3SAzat Khuzhin            "{",
633f0ded5f3SAzat Khuzhin            "  if (msg->%s_set != 1)" % name,
634f0ded5f3SAzat Khuzhin            "    return (-1);",
635f0ded5f3SAzat Khuzhin            "  *value = msg->%s_data;" % name,
636f0ded5f3SAzat Khuzhin            "  return (0);",
637f0ded5f3SAzat Khuzhin            "}",
638f0ded5f3SAzat Khuzhin        ]
639949cbd12SNiels Provos        return code
640949cbd12SNiels Provos
641949cbd12SNiels Provos    def CodeAssign(self):
642949cbd12SNiels Provos        name = self._name
643f0ded5f3SAzat Khuzhin        code = [
644f0ded5f3SAzat Khuzhin            "int",
645f0ded5f3SAzat Khuzhin            "%s_%s_assign(struct %s *msg, const %s *value)"
646f0ded5f3SAzat Khuzhin            % (self._struct.Name(), name, self._struct.Name(), self._ctype),
647f0ded5f3SAzat Khuzhin            "{",
648f0ded5f3SAzat Khuzhin            "  msg->%s_set = 1;" % name,
649f0ded5f3SAzat Khuzhin            "  memcpy(msg->%s_data, value, %s);" % (name, self._length),
650f0ded5f3SAzat Khuzhin            "  return (0);",
651f0ded5f3SAzat Khuzhin            "}",
652f0ded5f3SAzat Khuzhin        ]
653949cbd12SNiels Provos        return code
654949cbd12SNiels Provos
65568725dc8SNiels Provos    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
656f0ded5f3SAzat Khuzhin        code = [
657f0ded5f3SAzat Khuzhin            "if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, "
658f0ded5f3SAzat Khuzhin            "%(var)s, %(varlen)s) == -1) {",
65968725dc8SNiels Provos            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
660f0ded5f3SAzat Khuzhin            "  return (-1);",
661f0ded5f3SAzat Khuzhin            "}",
66232acc283SNiels Provos        ]
663f0ded5f3SAzat Khuzhin        return TranslateList(
664f0ded5f3SAzat Khuzhin            code,
665f0ded5f3SAzat Khuzhin            self.GetTranslation(
666f0ded5f3SAzat Khuzhin                {"var": var_name, "varlen": var_len, "buf": buf, "tag": tag_name}
667f0ded5f3SAzat Khuzhin            ),
668f0ded5f3SAzat Khuzhin        )
669949cbd12SNiels Provos
670f0ded5f3SAzat Khuzhin    @staticmethod
671f0ded5f3SAzat Khuzhin    def CodeMarshal(buf, tag_name, var_name, var_len):
672f0ded5f3SAzat Khuzhin        code = ["evtag_marshal(%s, %s, %s, %s);" % (buf, tag_name, var_name, var_len)]
673949cbd12SNiels Provos        return code
674949cbd12SNiels Provos
675949cbd12SNiels Provos    def CodeClear(self, structname):
676f0ded5f3SAzat Khuzhin        code = [
677f0ded5f3SAzat Khuzhin            "%s->%s_set = 0;" % (structname, self.Name()),
678f0ded5f3SAzat Khuzhin            "memset(%s->%s_data, 0, sizeof(%s->%s_data));"
679f0ded5f3SAzat Khuzhin            % (structname, self._name, structname, self._name),
680f0ded5f3SAzat Khuzhin        ]
681949cbd12SNiels Provos
682949cbd12SNiels Provos        return code
683949cbd12SNiels Provos
68468725dc8SNiels Provos    def CodeInitialize(self, name):
685f0ded5f3SAzat Khuzhin        code = [
686f0ded5f3SAzat Khuzhin            "memset(%s->%s_data, 0, sizeof(%s->%s_data));"
687f0ded5f3SAzat Khuzhin            % (name, self._name, name, self._name)
688f0ded5f3SAzat Khuzhin        ]
689949cbd12SNiels Provos        return code
690949cbd12SNiels Provos
691949cbd12SNiels Provos    def Verify(self):
692949cbd12SNiels Provos        if not self._length:
69337d3e16cSNiels Provos            raise RpcGenError(
69437d3e16cSNiels Provos                'Entry "%s" needs a length '
695f0ded5f3SAzat Khuzhin                "around line %d" % (self._name, self.LineCount())
696f0ded5f3SAzat Khuzhin            )
697949cbd12SNiels Provos
698f0ded5f3SAzat Khuzhin        super(EntryBytes, self).Verify()
699f0ded5f3SAzat Khuzhin
700949cbd12SNiels Provos
701949cbd12SNiels Provosclass EntryInt(Entry):
702f0ded5f3SAzat Khuzhin    def __init__(self, ent_type, name, tag, bits=32):
703949cbd12SNiels Provos        # Init base class
704f0ded5f3SAzat Khuzhin        super(EntryInt, self).__init__(ent_type, name, tag)
705949cbd12SNiels Provos
706f0ded5f3SAzat Khuzhin        self._can_be_array = True
70799a1063eSNiels Provos        if bits == 32:
708f0ded5f3SAzat Khuzhin            self._ctype = "ev_uint32_t"
709f0ded5f3SAzat Khuzhin            self._marshal_type = "int"
71099a1063eSNiels Provos        if bits == 64:
711f0ded5f3SAzat Khuzhin            self._ctype = "ev_uint64_t"
712f0ded5f3SAzat Khuzhin            self._marshal_type = "int64"
713949cbd12SNiels Provos
714f0ded5f3SAzat Khuzhin    @staticmethod
715f0ded5f3SAzat Khuzhin    def GetInitializer():
71668725dc8SNiels Provos        return "0"
71768725dc8SNiels Provos
718f0ded5f3SAzat Khuzhin    @staticmethod
719f0ded5f3SAzat Khuzhin    def CodeArrayFree(_var):
7207e3a7af7SNiels Provos        return []
72168725dc8SNiels Provos
722f0ded5f3SAzat Khuzhin    @staticmethod
723f0ded5f3SAzat Khuzhin    def CodeArrayAssign(varname, srcvar):
724f0ded5f3SAzat Khuzhin        return ["%(varname)s = %(srcvar)s;" % {"varname": varname, "srcvar": srcvar}]
72568725dc8SNiels Provos
726f0ded5f3SAzat Khuzhin    @staticmethod
727f0ded5f3SAzat Khuzhin    def CodeArrayAdd(varname, value):
72868725dc8SNiels Provos        """Returns a new entry of this type."""
729f0ded5f3SAzat Khuzhin        return ["%(varname)s = %(value)s;" % {"varname": varname, "value": value}]
73068725dc8SNiels Provos
731f0ded5f3SAzat Khuzhin    def CodeUnmarshal(self, buf, tag_name, var_name, _var_len):
73299a1063eSNiels Provos        code = [
733f0ded5f3SAzat Khuzhin            "if (evtag_unmarshal_%(ma)s(%(buf)s, %(tag)s, &%(var)s) == -1) {",
73468725dc8SNiels Provos            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
735f0ded5f3SAzat Khuzhin            "  return (-1);",
736f0ded5f3SAzat Khuzhin            "}",
737f0ded5f3SAzat Khuzhin        ]
738f0ded5f3SAzat Khuzhin        code = "\n".join(code) % self.GetTranslation(
739f0ded5f3SAzat Khuzhin            {"ma": self._marshal_type, "buf": buf, "tag": tag_name, "var": var_name}
740f0ded5f3SAzat Khuzhin        )
741f0ded5f3SAzat Khuzhin        return code.split("\n")
742949cbd12SNiels Provos
743f0ded5f3SAzat Khuzhin    def CodeMarshal(self, buf, tag_name, var_name, _var_len):
74499a1063eSNiels Provos        code = [
745f0ded5f3SAzat Khuzhin            "evtag_marshal_%s(%s, %s, %s);"
746f0ded5f3SAzat Khuzhin            % (self._marshal_type, buf, tag_name, var_name)
747f0ded5f3SAzat Khuzhin        ]
748949cbd12SNiels Provos        return code
749949cbd12SNiels Provos
750949cbd12SNiels Provos    def Declaration(self):
751f0ded5f3SAzat Khuzhin        dcl = ["%s %s_data;" % (self._ctype, self._name)]
752949cbd12SNiels Provos
753949cbd12SNiels Provos        return dcl
754949cbd12SNiels Provos
75568725dc8SNiels Provos    def CodeInitialize(self, name):
756f0ded5f3SAzat Khuzhin        code = ["%s->%s_data = 0;" % (name, self._name)]
75785053473SNiels Provos        return code
75885053473SNiels Provos
759f0ded5f3SAzat Khuzhin
760949cbd12SNiels Provosclass EntryString(Entry):
761f0ded5f3SAzat Khuzhin    def __init__(self, ent_type, name, tag):
762949cbd12SNiels Provos        # Init base class
763f0ded5f3SAzat Khuzhin        super(EntryString, self).__init__(ent_type, name, tag)
764949cbd12SNiels Provos
765f0ded5f3SAzat Khuzhin        self._can_be_array = True
766f0ded5f3SAzat Khuzhin        self._ctype = "char *"
767949cbd12SNiels Provos
768f0ded5f3SAzat Khuzhin    @staticmethod
769f0ded5f3SAzat Khuzhin    def GetInitializer():
77068725dc8SNiels Provos        return "NULL"
77168725dc8SNiels Provos
772f0ded5f3SAzat Khuzhin    @staticmethod
773f0ded5f3SAzat Khuzhin    def CodeArrayFree(varname):
774f0ded5f3SAzat Khuzhin        code = ["if (%(var)s != NULL) free(%(var)s);"]
7757e3a7af7SNiels Provos
776f0ded5f3SAzat Khuzhin        return TranslateList(code, {"var": varname})
7777e3a7af7SNiels Provos
778f0ded5f3SAzat Khuzhin    @staticmethod
779f0ded5f3SAzat Khuzhin    def CodeArrayAssign(varname, srcvar):
7807e3a7af7SNiels Provos        code = [
781f0ded5f3SAzat Khuzhin            "if (%(var)s != NULL)",
782f0ded5f3SAzat Khuzhin            "  free(%(var)s);",
783f0ded5f3SAzat Khuzhin            "%(var)s = strdup(%(srcvar)s);",
784f0ded5f3SAzat Khuzhin            "if (%(var)s == NULL) {",
7857e3a7af7SNiels Provos            '  event_warnx("%%s: strdup", __func__);',
786f0ded5f3SAzat Khuzhin            "  return (-1);",
787f0ded5f3SAzat Khuzhin            "}",
788f0ded5f3SAzat Khuzhin        ]
7897e3a7af7SNiels Provos
790f0ded5f3SAzat Khuzhin        return TranslateList(code, {"var": varname, "srcvar": srcvar})
7917e3a7af7SNiels Provos
792f0ded5f3SAzat Khuzhin    @staticmethod
793f0ded5f3SAzat Khuzhin    def CodeArrayAdd(varname, value):
7947e3a7af7SNiels Provos        code = [
795f0ded5f3SAzat Khuzhin            "if (%(value)s != NULL) {",
796f0ded5f3SAzat Khuzhin            "  %(var)s = strdup(%(value)s);",
797f0ded5f3SAzat Khuzhin            "  if (%(var)s == NULL) {",
798f0ded5f3SAzat Khuzhin            "    goto error;",
799f0ded5f3SAzat Khuzhin            "  }",
800f0ded5f3SAzat Khuzhin            "} else {",
801f0ded5f3SAzat Khuzhin            "  %(var)s = NULL;",
802f0ded5f3SAzat Khuzhin            "}",
803f0ded5f3SAzat Khuzhin        ]
8047e3a7af7SNiels Provos
805f0ded5f3SAzat Khuzhin        return TranslateList(code, {"var": varname, "value": value})
8067e3a7af7SNiels Provos
80768725dc8SNiels Provos    def GetVarLen(self, var):
808f0ded5f3SAzat Khuzhin        return "strlen(%s)" % self.GetVarName(var)
80968725dc8SNiels Provos
810f0ded5f3SAzat Khuzhin    @staticmethod
811f0ded5f3SAzat Khuzhin    def CodeMakeInitalize(varname):
812f0ded5f3SAzat Khuzhin        return "%(varname)s = NULL;" % {"varname": varname}
81368725dc8SNiels Provos
814949cbd12SNiels Provos    def CodeAssign(self):
8153c1a6a68SNiels Provos        code = """int
8163c1a6a68SNiels Provos%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
8173c1a6a68SNiels Provos    const %(ctype)s value)
8183c1a6a68SNiels Provos{
8193c1a6a68SNiels Provos  if (msg->%(name)s_data != NULL)
8203c1a6a68SNiels Provos    free(msg->%(name)s_data);
8213c1a6a68SNiels Provos  if ((msg->%(name)s_data = strdup(value)) == NULL)
8223c1a6a68SNiels Provos    return (-1);
8233c1a6a68SNiels Provos  msg->%(name)s_set = 1;
8243c1a6a68SNiels Provos  return (0);
825f0ded5f3SAzat Khuzhin}""" % (
826f0ded5f3SAzat Khuzhin            self.GetTranslation()
827f0ded5f3SAzat Khuzhin        )
8283c1a6a68SNiels Provos
829f0ded5f3SAzat Khuzhin        return code.split("\n")
830949cbd12SNiels Provos
831f0ded5f3SAzat Khuzhin    def CodeUnmarshal(self, buf, tag_name, var_name, _var_len):
832f0ded5f3SAzat Khuzhin        code = [
833f0ded5f3SAzat Khuzhin            "if (evtag_unmarshal_string(%(buf)s, %(tag)s, &%(var)s) == -1) {",
83468725dc8SNiels Provos            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
835f0ded5f3SAzat Khuzhin            "  return (-1);",
836f0ded5f3SAzat Khuzhin            "}",
83732acc283SNiels Provos        ]
838f0ded5f3SAzat Khuzhin        code = "\n".join(code) % self.GetTranslation(
839f0ded5f3SAzat Khuzhin            {"buf": buf, "tag": tag_name, "var": var_name}
840f0ded5f3SAzat Khuzhin        )
841f0ded5f3SAzat Khuzhin        return code.split("\n")
842949cbd12SNiels Provos
843f0ded5f3SAzat Khuzhin    @staticmethod
844f0ded5f3SAzat Khuzhin    def CodeMarshal(buf, tag_name, var_name, _var_len):
845f0ded5f3SAzat Khuzhin        code = ["evtag_marshal_string(%s, %s, %s);" % (buf, tag_name, var_name)]
846949cbd12SNiels Provos        return code
847949cbd12SNiels Provos
848949cbd12SNiels Provos    def CodeClear(self, structname):
849f0ded5f3SAzat Khuzhin        code = [
850f0ded5f3SAzat Khuzhin            "if (%s->%s_set == 1) {" % (structname, self.Name()),
851f0ded5f3SAzat Khuzhin            "  free(%s->%s_data);" % (structname, self.Name()),
852f0ded5f3SAzat Khuzhin            "  %s->%s_data = NULL;" % (structname, self.Name()),
853f0ded5f3SAzat Khuzhin            "  %s->%s_set = 0;" % (structname, self.Name()),
854f0ded5f3SAzat Khuzhin            "}",
855949cbd12SNiels Provos        ]
856949cbd12SNiels Provos
857949cbd12SNiels Provos        return code
858949cbd12SNiels Provos
85968725dc8SNiels Provos    def CodeInitialize(self, name):
860f0ded5f3SAzat Khuzhin        code = ["%s->%s_data = NULL;" % (name, self._name)]
861949cbd12SNiels Provos        return code
862949cbd12SNiels Provos
863949cbd12SNiels Provos    def CodeFree(self, name):
864f0ded5f3SAzat Khuzhin        code = [
865f0ded5f3SAzat Khuzhin            "if (%s->%s_data != NULL)" % (name, self._name),
866f0ded5f3SAzat Khuzhin            "    free (%s->%s_data);" % (name, self._name),
867f0ded5f3SAzat Khuzhin        ]
868949cbd12SNiels Provos
869949cbd12SNiels Provos        return code
870949cbd12SNiels Provos
871949cbd12SNiels Provos    def Declaration(self):
872f0ded5f3SAzat Khuzhin        dcl = ["char *%s_data;" % self._name]
873949cbd12SNiels Provos
874949cbd12SNiels Provos        return dcl
875949cbd12SNiels Provos
876f0ded5f3SAzat Khuzhin
877949cbd12SNiels Provosclass EntryStruct(Entry):
878f0ded5f3SAzat Khuzhin    def __init__(self, ent_type, name, tag, refname):
879949cbd12SNiels Provos        # Init base class
880f0ded5f3SAzat Khuzhin        super(EntryStruct, self).__init__(ent_type, name, tag)
881949cbd12SNiels Provos
88268725dc8SNiels Provos        self._optpointer = False
883f0ded5f3SAzat Khuzhin        self._can_be_array = True
884949cbd12SNiels Provos        self._refname = refname
885f0ded5f3SAzat Khuzhin        self._ctype = "struct %s*" % refname
88668725dc8SNiels Provos        self._optaddarg = False
88768725dc8SNiels Provos
88868725dc8SNiels Provos    def GetInitializer(self):
88968725dc8SNiels Provos        return "NULL"
89068725dc8SNiels Provos
891f0ded5f3SAzat Khuzhin    def GetVarLen(self, _var):
892f0ded5f3SAzat Khuzhin        return "-1"
89368725dc8SNiels Provos
894f0ded5f3SAzat Khuzhin    def CodeArrayAdd(self, varname, _value):
8957e3a7af7SNiels Provos        code = [
896f0ded5f3SAzat Khuzhin            "%(varname)s = %(refname)s_new();",
897f0ded5f3SAzat Khuzhin            "if (%(varname)s == NULL)",
898f0ded5f3SAzat Khuzhin            "  goto error;",
899f0ded5f3SAzat Khuzhin        ]
9007e3a7af7SNiels Provos
901f0ded5f3SAzat Khuzhin        return TranslateList(code, self.GetTranslation({"varname": varname}))
90268725dc8SNiels Provos
90368725dc8SNiels Provos    def CodeArrayFree(self, var):
904f0ded5f3SAzat Khuzhin        code = ["%(refname)s_free(%(var)s);" % self.GetTranslation({"var": var})]
90568725dc8SNiels Provos        return code
90668725dc8SNiels Provos
90768725dc8SNiels Provos    def CodeArrayAssign(self, var, srcvar):
9087e3a7af7SNiels Provos        code = [
909f0ded5f3SAzat Khuzhin            "int had_error = 0;",
910f0ded5f3SAzat Khuzhin            "struct evbuffer *tmp = NULL;",
911f0ded5f3SAzat Khuzhin            "%(refname)s_clear(%(var)s);",
912f0ded5f3SAzat Khuzhin            "if ((tmp = evbuffer_new()) == NULL) {",
9137e3a7af7SNiels Provos            '  event_warn("%%s: evbuffer_new()", __func__);',
914f0ded5f3SAzat Khuzhin            "  had_error = 1;",
915f0ded5f3SAzat Khuzhin            "  goto done;",
916f0ded5f3SAzat Khuzhin            "}",
917f0ded5f3SAzat Khuzhin            "%(refname)s_marshal(tmp, %(srcvar)s);",
918f0ded5f3SAzat Khuzhin            "if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {",
9197e3a7af7SNiels Provos            '  event_warnx("%%s: %(refname)s_unmarshal", __func__);',
920f0ded5f3SAzat Khuzhin            "  had_error = 1;",
921f0ded5f3SAzat Khuzhin            "  goto done;",
922f0ded5f3SAzat Khuzhin            "}",
923f0ded5f3SAzat Khuzhin            "done:",
924f0ded5f3SAzat Khuzhin            "if (tmp != NULL)",
925f0ded5f3SAzat Khuzhin            "  evbuffer_free(tmp);",
926f0ded5f3SAzat Khuzhin            "if (had_error) {",
927f0ded5f3SAzat Khuzhin            "  %(refname)s_clear(%(var)s);",
928f0ded5f3SAzat Khuzhin            "  return (-1);",
929f0ded5f3SAzat Khuzhin            "}",
930f0ded5f3SAzat Khuzhin        ]
9317e3a7af7SNiels Provos
932f0ded5f3SAzat Khuzhin        return TranslateList(code, self.GetTranslation({"var": var, "srcvar": srcvar}))
933949cbd12SNiels Provos
934949cbd12SNiels Provos    def CodeGet(self):
935949cbd12SNiels Provos        name = self._name
936f0ded5f3SAzat Khuzhin        code = [
937f0ded5f3SAzat Khuzhin            "int",
938f0ded5f3SAzat Khuzhin            "%s_%s_get(struct %s *msg, %s *value)"
939f0ded5f3SAzat Khuzhin            % (self._struct.Name(), name, self._struct.Name(), self._ctype),
940f0ded5f3SAzat Khuzhin            "{",
941f0ded5f3SAzat Khuzhin            "  if (msg->%s_set != 1) {" % name,
942f0ded5f3SAzat Khuzhin            "    msg->%s_data = %s_new();" % (name, self._refname),
943f0ded5f3SAzat Khuzhin            "    if (msg->%s_data == NULL)" % name,
944f0ded5f3SAzat Khuzhin            "      return (-1);",
945f0ded5f3SAzat Khuzhin            "    msg->%s_set = 1;" % name,
946f0ded5f3SAzat Khuzhin            "  }",
947f0ded5f3SAzat Khuzhin            "  *value = msg->%s_data;" % name,
948f0ded5f3SAzat Khuzhin            "  return (0);",
949f0ded5f3SAzat Khuzhin            "}",
950f0ded5f3SAzat Khuzhin        ]
951949cbd12SNiels Provos        return code
952949cbd12SNiels Provos
953949cbd12SNiels Provos    def CodeAssign(self):
954f0ded5f3SAzat Khuzhin        code = (
955f0ded5f3SAzat Khuzhin            """int
9563c1a6a68SNiels Provos%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
9573c1a6a68SNiels Provos    const %(ctype)s value)
9583c1a6a68SNiels Provos{
9593c1a6a68SNiels Provos   struct evbuffer *tmp = NULL;
9603c1a6a68SNiels Provos   if (msg->%(name)s_set) {
9613c1a6a68SNiels Provos     %(refname)s_clear(msg->%(name)s_data);
9623c1a6a68SNiels Provos     msg->%(name)s_set = 0;
9633c1a6a68SNiels Provos   } else {
9643c1a6a68SNiels Provos     msg->%(name)s_data = %(refname)s_new();
9653c1a6a68SNiels Provos     if (msg->%(name)s_data == NULL) {
9663c1a6a68SNiels Provos       event_warn("%%s: %(refname)s_new()", __func__);
9673c1a6a68SNiels Provos       goto error;
9683c1a6a68SNiels Provos     }
9693c1a6a68SNiels Provos   }
9703c1a6a68SNiels Provos   if ((tmp = evbuffer_new()) == NULL) {
9713c1a6a68SNiels Provos     event_warn("%%s: evbuffer_new()", __func__);
9723c1a6a68SNiels Provos     goto error;
9733c1a6a68SNiels Provos   }
9743c1a6a68SNiels Provos   %(refname)s_marshal(tmp, value);
9753c1a6a68SNiels Provos   if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) {
9763c1a6a68SNiels Provos     event_warnx("%%s: %(refname)s_unmarshal", __func__);
9773c1a6a68SNiels Provos     goto error;
9783c1a6a68SNiels Provos   }
9793c1a6a68SNiels Provos   msg->%(name)s_set = 1;
9803c1a6a68SNiels Provos   evbuffer_free(tmp);
9813c1a6a68SNiels Provos   return (0);
9823c1a6a68SNiels Provos error:
9833c1a6a68SNiels Provos   if (tmp != NULL)
9843c1a6a68SNiels Provos     evbuffer_free(tmp);
9853c1a6a68SNiels Provos   if (msg->%(name)s_data != NULL) {
9863c1a6a68SNiels Provos     %(refname)s_free(msg->%(name)s_data);
9873c1a6a68SNiels Provos     msg->%(name)s_data = NULL;
9883c1a6a68SNiels Provos   }
9893c1a6a68SNiels Provos   return (-1);
990f0ded5f3SAzat Khuzhin}"""
991f0ded5f3SAzat Khuzhin            % self.GetTranslation()
992f0ded5f3SAzat Khuzhin        )
993f0ded5f3SAzat Khuzhin        return code.split("\n")
994949cbd12SNiels Provos
99568725dc8SNiels Provos    def CodeComplete(self, structname, var_name):
996f0ded5f3SAzat Khuzhin        code = [
997f0ded5f3SAzat Khuzhin            "if (%(structname)s->%(name)s_set && "
998f0ded5f3SAzat Khuzhin            "%(refname)s_complete(%(var)s) == -1)",
999f0ded5f3SAzat Khuzhin            "  return (-1);",
100032acc283SNiels Provos        ]
1001949cbd12SNiels Provos
1002f0ded5f3SAzat Khuzhin        return TranslateList(
1003f0ded5f3SAzat Khuzhin            code, self.GetTranslation({"structname": structname, "var": var_name})
1004f0ded5f3SAzat Khuzhin        )
1005f0ded5f3SAzat Khuzhin
1006f0ded5f3SAzat Khuzhin    def CodeUnmarshal(self, buf, tag_name, var_name, _var_len):
1007f0ded5f3SAzat Khuzhin        code = [
1008f0ded5f3SAzat Khuzhin            "%(var)s = %(refname)s_new();",
1009f0ded5f3SAzat Khuzhin            "if (%(var)s == NULL)",
1010f0ded5f3SAzat Khuzhin            "  return (-1);",
1011f0ded5f3SAzat Khuzhin            "if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag)s, ",
1012f0ded5f3SAzat Khuzhin            "    %(var)s) == -1) {",
1013f0ded5f3SAzat Khuzhin            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
1014f0ded5f3SAzat Khuzhin            "  return (-1);",
1015f0ded5f3SAzat Khuzhin            "}",
1016f0ded5f3SAzat Khuzhin        ]
1017f0ded5f3SAzat Khuzhin        code = "\n".join(code) % self.GetTranslation(
1018f0ded5f3SAzat Khuzhin            {"buf": buf, "tag": tag_name, "var": var_name}
1019f0ded5f3SAzat Khuzhin        )
1020f0ded5f3SAzat Khuzhin        return code.split("\n")
1021f0ded5f3SAzat Khuzhin
1022f0ded5f3SAzat Khuzhin    def CodeMarshal(self, buf, tag_name, var_name, _var_len):
1023f0ded5f3SAzat Khuzhin        code = [
1024f0ded5f3SAzat Khuzhin            "evtag_marshal_%s(%s, %s, %s);" % (self._refname, buf, tag_name, var_name)
1025f0ded5f3SAzat Khuzhin        ]
1026949cbd12SNiels Provos        return code
1027949cbd12SNiels Provos
1028949cbd12SNiels Provos    def CodeClear(self, structname):
1029f0ded5f3SAzat Khuzhin        code = [
1030f0ded5f3SAzat Khuzhin            "if (%s->%s_set == 1) {" % (structname, self.Name()),
1031f0ded5f3SAzat Khuzhin            "  %s_free(%s->%s_data);" % (self._refname, structname, self.Name()),
1032f0ded5f3SAzat Khuzhin            "  %s->%s_data = NULL;" % (structname, self.Name()),
1033f0ded5f3SAzat Khuzhin            "  %s->%s_set = 0;" % (structname, self.Name()),
1034f0ded5f3SAzat Khuzhin            "}",
1035949cbd12SNiels Provos        ]
1036949cbd12SNiels Provos
1037949cbd12SNiels Provos        return code
1038949cbd12SNiels Provos
103968725dc8SNiels Provos    def CodeInitialize(self, name):
1040f0ded5f3SAzat Khuzhin        code = ["%s->%s_data = NULL;" % (name, self._name)]
1041949cbd12SNiels Provos        return code
1042949cbd12SNiels Provos
1043949cbd12SNiels Provos    def CodeFree(self, name):
1044f0ded5f3SAzat Khuzhin        code = [
1045f0ded5f3SAzat Khuzhin            "if (%s->%s_data != NULL)" % (name, self._name),
1046f0ded5f3SAzat Khuzhin            "    %s_free(%s->%s_data);" % (self._refname, name, self._name),
1047f0ded5f3SAzat Khuzhin        ]
1048949cbd12SNiels Provos
1049949cbd12SNiels Provos        return code
1050949cbd12SNiels Provos
1051949cbd12SNiels Provos    def Declaration(self):
1052f0ded5f3SAzat Khuzhin        dcl = ["%s %s_data;" % (self._ctype, self._name)]
1053949cbd12SNiels Provos
1054949cbd12SNiels Provos        return dcl
1055949cbd12SNiels Provos
1056f0ded5f3SAzat Khuzhin
1057949cbd12SNiels Provosclass EntryVarBytes(Entry):
1058f0ded5f3SAzat Khuzhin    def __init__(self, ent_type, name, tag):
1059949cbd12SNiels Provos        # Init base class
1060f0ded5f3SAzat Khuzhin        super(EntryVarBytes, self).__init__(ent_type, name, tag)
1061949cbd12SNiels Provos
1062f0ded5f3SAzat Khuzhin        self._ctype = "ev_uint8_t *"
1063949cbd12SNiels Provos
1064f0ded5f3SAzat Khuzhin    @staticmethod
1065f0ded5f3SAzat Khuzhin    def GetInitializer():
106668725dc8SNiels Provos        return "NULL"
106768725dc8SNiels Provos
106868725dc8SNiels Provos    def GetVarLen(self, var):
1069f0ded5f3SAzat Khuzhin        return "%(var)s->%(name)s_length" % self.GetTranslation({"var": var})
107068725dc8SNiels Provos
1071f0ded5f3SAzat Khuzhin    @staticmethod
1072f0ded5f3SAzat Khuzhin    def CodeArrayAdd(varname, _value):
107368725dc8SNiels Provos        # xxx: copy
1074f0ded5f3SAzat Khuzhin        return ["%(varname)s = NULL;" % {"varname": varname}]
107568725dc8SNiels Provos
1076aaf56fb6SNiels Provos    def GetDeclaration(self, funcname):
1077f0ded5f3SAzat Khuzhin        code = [
1078f0ded5f3SAzat Khuzhin            "int %s(struct %s *, %s *, ev_uint32_t *);"
1079f0ded5f3SAzat Khuzhin            % (funcname, self._struct.Name(), self._ctype)
1080f0ded5f3SAzat Khuzhin        ]
1081aaf56fb6SNiels Provos        return code
1082aaf56fb6SNiels Provos
1083949cbd12SNiels Provos    def AssignDeclaration(self, funcname):
1084f0ded5f3SAzat Khuzhin        code = [
1085f0ded5f3SAzat Khuzhin            "int %s(struct %s *, const %s, ev_uint32_t);"
1086f0ded5f3SAzat Khuzhin            % (funcname, self._struct.Name(), self._ctype)
1087f0ded5f3SAzat Khuzhin        ]
1088949cbd12SNiels Provos        return code
1089949cbd12SNiels Provos
1090949cbd12SNiels Provos    def CodeAssign(self):
1091949cbd12SNiels Provos        name = self._name
1092f0ded5f3SAzat Khuzhin        code = [
1093f0ded5f3SAzat Khuzhin            "int",
1094f0ded5f3SAzat Khuzhin            "%s_%s_assign(struct %s *msg, "
1095f0ded5f3SAzat Khuzhin            "const %s value, ev_uint32_t len)"
1096f0ded5f3SAzat Khuzhin            % (self._struct.Name(), name, self._struct.Name(), self._ctype),
1097f0ded5f3SAzat Khuzhin            "{",
1098f0ded5f3SAzat Khuzhin            "  if (msg->%s_data != NULL)" % name,
1099f0ded5f3SAzat Khuzhin            "    free (msg->%s_data);" % name,
1100f0ded5f3SAzat Khuzhin            "  msg->%s_data = malloc(len);" % name,
1101f0ded5f3SAzat Khuzhin            "  if (msg->%s_data == NULL)" % name,
1102f0ded5f3SAzat Khuzhin            "    return (-1);",
1103f0ded5f3SAzat Khuzhin            "  msg->%s_set = 1;" % name,
1104f0ded5f3SAzat Khuzhin            "  msg->%s_length = len;" % name,
1105f0ded5f3SAzat Khuzhin            "  memcpy(msg->%s_data, value, len);" % name,
1106f0ded5f3SAzat Khuzhin            "  return (0);",
1107f0ded5f3SAzat Khuzhin            "}",
1108f0ded5f3SAzat Khuzhin        ]
1109949cbd12SNiels Provos        return code
1110949cbd12SNiels Provos
1111aaf56fb6SNiels Provos    def CodeGet(self):
1112aaf56fb6SNiels Provos        name = self._name
1113f0ded5f3SAzat Khuzhin        code = [
1114f0ded5f3SAzat Khuzhin            "int",
1115f0ded5f3SAzat Khuzhin            "%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)"
1116f0ded5f3SAzat Khuzhin            % (self._struct.Name(), name, self._struct.Name(), self._ctype),
1117f0ded5f3SAzat Khuzhin            "{",
1118f0ded5f3SAzat Khuzhin            "  if (msg->%s_set != 1)" % name,
1119f0ded5f3SAzat Khuzhin            "    return (-1);",
1120f0ded5f3SAzat Khuzhin            "  *value = msg->%s_data;" % name,
1121f0ded5f3SAzat Khuzhin            "  *plen = msg->%s_length;" % name,
1122f0ded5f3SAzat Khuzhin            "  return (0);",
1123f0ded5f3SAzat Khuzhin            "}",
1124f0ded5f3SAzat Khuzhin        ]
1125aaf56fb6SNiels Provos        return code
1126aaf56fb6SNiels Provos
112768725dc8SNiels Provos    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
1128f0ded5f3SAzat Khuzhin        code = [
1129f0ded5f3SAzat Khuzhin            "if (evtag_payload_length(%(buf)s, &%(varlen)s) == -1)",
1130f0ded5f3SAzat Khuzhin            "  return (-1);",
11317000fe66SNiels Provos            # We do not want DoS opportunities
1132f0ded5f3SAzat Khuzhin            "if (%(varlen)s > evbuffer_get_length(%(buf)s))",
1133f0ded5f3SAzat Khuzhin            "  return (-1);",
1134f0ded5f3SAzat Khuzhin            "if ((%(var)s = malloc(%(varlen)s)) == NULL)",
1135f0ded5f3SAzat Khuzhin            "  return (-1);",
1136f0ded5f3SAzat Khuzhin            "if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, %(var)s, "
1137f0ded5f3SAzat Khuzhin            "%(varlen)s) == -1) {",
113868725dc8SNiels Provos            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
1139f0ded5f3SAzat Khuzhin            "  return (-1);",
1140f0ded5f3SAzat Khuzhin            "}",
114132acc283SNiels Provos        ]
1142f0ded5f3SAzat Khuzhin        code = "\n".join(code) % self.GetTranslation(
1143f0ded5f3SAzat Khuzhin            {"buf": buf, "tag": tag_name, "var": var_name, "varlen": var_len}
1144f0ded5f3SAzat Khuzhin        )
1145f0ded5f3SAzat Khuzhin        return code.split("\n")
1146949cbd12SNiels Provos
1147f0ded5f3SAzat Khuzhin    @staticmethod
1148f0ded5f3SAzat Khuzhin    def CodeMarshal(buf, tag_name, var_name, var_len):
1149f0ded5f3SAzat Khuzhin        code = ["evtag_marshal(%s, %s, %s, %s);" % (buf, tag_name, var_name, var_len)]
1150949cbd12SNiels Provos        return code
1151949cbd12SNiels Provos
1152949cbd12SNiels Provos    def CodeClear(self, structname):
1153f0ded5f3SAzat Khuzhin        code = [
1154f0ded5f3SAzat Khuzhin            "if (%s->%s_set == 1) {" % (structname, self.Name()),
1155f0ded5f3SAzat Khuzhin            "  free (%s->%s_data);" % (structname, self.Name()),
1156f0ded5f3SAzat Khuzhin            "  %s->%s_data = NULL;" % (structname, self.Name()),
1157f0ded5f3SAzat Khuzhin            "  %s->%s_length = 0;" % (structname, self.Name()),
1158f0ded5f3SAzat Khuzhin            "  %s->%s_set = 0;" % (structname, self.Name()),
1159f0ded5f3SAzat Khuzhin            "}",
1160949cbd12SNiels Provos        ]
1161949cbd12SNiels Provos
1162949cbd12SNiels Provos        return code
1163949cbd12SNiels Provos
116468725dc8SNiels Provos    def CodeInitialize(self, name):
1165f0ded5f3SAzat Khuzhin        code = [
1166f0ded5f3SAzat Khuzhin            "%s->%s_data = NULL;" % (name, self._name),
1167f0ded5f3SAzat Khuzhin            "%s->%s_length = 0;" % (name, self._name),
1168f0ded5f3SAzat Khuzhin        ]
1169949cbd12SNiels Provos        return code
1170949cbd12SNiels Provos
1171949cbd12SNiels Provos    def CodeFree(self, name):
1172f0ded5f3SAzat Khuzhin        code = [
1173f0ded5f3SAzat Khuzhin            "if (%s->%s_data != NULL)" % (name, self._name),
1174f0ded5f3SAzat Khuzhin            "    free(%s->%s_data);" % (name, self._name),
1175f0ded5f3SAzat Khuzhin        ]
1176949cbd12SNiels Provos
1177949cbd12SNiels Provos        return code
1178949cbd12SNiels Provos
1179949cbd12SNiels Provos    def Declaration(self):
1180f0ded5f3SAzat Khuzhin        dcl = [
1181f0ded5f3SAzat Khuzhin            "ev_uint8_t *%s_data;" % self._name,
1182f0ded5f3SAzat Khuzhin            "ev_uint32_t %s_length;" % self._name,
1183f0ded5f3SAzat Khuzhin        ]
1184949cbd12SNiels Provos
1185949cbd12SNiels Provos        return dcl
1186949cbd12SNiels Provos
1187f0ded5f3SAzat Khuzhin
1188b4ab56dcSNiels Provosclass EntryArray(Entry):
1189f0ded5f3SAzat Khuzhin    _index = None
1190f0ded5f3SAzat Khuzhin
1191b4ab56dcSNiels Provos    def __init__(self, entry):
1192b4ab56dcSNiels Provos        # Init base class
1193f0ded5f3SAzat Khuzhin        super(EntryArray, self).__init__(entry._type, entry._name, entry._tag)
1194b4ab56dcSNiels Provos
1195b4ab56dcSNiels Provos        self._entry = entry
1196b4ab56dcSNiels Provos        self._refname = entry._refname
119768725dc8SNiels Provos        self._ctype = self._entry._ctype
119868725dc8SNiels Provos        self._optional = True
119968725dc8SNiels Provos        self._optpointer = self._entry._optpointer
120068725dc8SNiels Provos        self._optaddarg = self._entry._optaddarg
120168725dc8SNiels Provos
120268725dc8SNiels Provos        # provide a new function for accessing the variable name
120368725dc8SNiels Provos        def GetVarName(var_name):
1204f0ded5f3SAzat Khuzhin            return "%(var)s->%(name)s_data[%(index)s]" % self._entry.GetTranslation(
1205f0ded5f3SAzat Khuzhin                {"var": var_name, "index": self._index}
1206f0ded5f3SAzat Khuzhin            )
1207f0ded5f3SAzat Khuzhin
120868725dc8SNiels Provos        self._entry.GetVarName = GetVarName
120968725dc8SNiels Provos
121068725dc8SNiels Provos    def GetInitializer(self):
121168725dc8SNiels Provos        return "NULL"
121268725dc8SNiels Provos
1213f0ded5f3SAzat Khuzhin    def GetVarName(self, var):
1214f0ded5f3SAzat Khuzhin        return var
121568725dc8SNiels Provos
1216f0ded5f3SAzat Khuzhin    def GetVarLen(self, _var_name):
1217f0ded5f3SAzat Khuzhin        return "-1"
1218b4ab56dcSNiels Provos
1219b4ab56dcSNiels Provos    def GetDeclaration(self, funcname):
1220b4ab56dcSNiels Provos        """Allows direct access to elements of the array."""
12213c1a6a68SNiels Provos        code = [
1222f0ded5f3SAzat Khuzhin            "int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);"
1223f0ded5f3SAzat Khuzhin            % self.GetTranslation({"funcname": funcname})
1224f0ded5f3SAzat Khuzhin        ]
1225b4ab56dcSNiels Provos        return code
1226b4ab56dcSNiels Provos
1227b4ab56dcSNiels Provos    def AssignDeclaration(self, funcname):
1228f0ded5f3SAzat Khuzhin        code = [
1229f0ded5f3SAzat Khuzhin            "int %s(struct %s *, int, const %s);"
1230f0ded5f3SAzat Khuzhin            % (funcname, self._struct.Name(), self._ctype)
1231f0ded5f3SAzat Khuzhin        ]
1232b4ab56dcSNiels Provos        return code
1233b4ab56dcSNiels Provos
1234b4ab56dcSNiels Provos    def AddDeclaration(self, funcname):
123568725dc8SNiels Provos        code = [
1236f0ded5f3SAzat Khuzhin            "%(ctype)s %(optpointer)s "
1237f0ded5f3SAzat Khuzhin            "%(funcname)s(struct %(parent_name)s *msg%(optaddarg)s);"
1238f0ded5f3SAzat Khuzhin            % self.GetTranslation({"funcname": funcname})
1239f0ded5f3SAzat Khuzhin        ]
1240b4ab56dcSNiels Provos        return code
1241b4ab56dcSNiels Provos
1242b4ab56dcSNiels Provos    def CodeGet(self):
12433c1a6a68SNiels Provos        code = """int
12443c1a6a68SNiels Provos%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset,
12453c1a6a68SNiels Provos    %(ctype)s *value)
12463c1a6a68SNiels Provos{
12473c1a6a68SNiels Provos  if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length)
12483c1a6a68SNiels Provos    return (-1);
12493c1a6a68SNiels Provos  *value = msg->%(name)s_data[offset];
12503c1a6a68SNiels Provos  return (0);
1251f0ded5f3SAzat Khuzhin}
1252f0ded5f3SAzat Khuzhin""" % (
1253f0ded5f3SAzat Khuzhin            self.GetTranslation()
1254f0ded5f3SAzat Khuzhin        )
12553c1a6a68SNiels Provos
1256f0ded5f3SAzat Khuzhin        return code.splitlines()
1257b4ab56dcSNiels Provos
1258b4ab56dcSNiels Provos    def CodeAssign(self):
12597e3a7af7SNiels Provos        code = [
1260f0ded5f3SAzat Khuzhin            "int",
1261f0ded5f3SAzat Khuzhin            "%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,",
1262f0ded5f3SAzat Khuzhin            "  const %(ctype)s value)",
1263f0ded5f3SAzat Khuzhin            "{",
1264f0ded5f3SAzat Khuzhin            "  if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)",
1265f0ded5f3SAzat Khuzhin            "    return (-1);",
1266f0ded5f3SAzat Khuzhin            "",
1267f0ded5f3SAzat Khuzhin            "  {",
1268f0ded5f3SAzat Khuzhin        ]
12697e3a7af7SNiels Provos        code = TranslateList(code, self.GetTranslation())
12707e3a7af7SNiels Provos
127168725dc8SNiels Provos        codearrayassign = self._entry.CodeArrayAssign(
1272f0ded5f3SAzat Khuzhin            "msg->%(name)s_data[off]" % self.GetTranslation(), "value"
1273f0ded5f3SAzat Khuzhin        )
1274f0ded5f3SAzat Khuzhin        code += ["    " + x for x in codearrayassign]
12753c1a6a68SNiels Provos
1276f0ded5f3SAzat Khuzhin        code += TranslateList(["  }", "  return (0);", "}"], self.GetTranslation())
12777e3a7af7SNiels Provos
12787e3a7af7SNiels Provos        return code
1279b4ab56dcSNiels Provos
1280b4ab56dcSNiels Provos    def CodeAdd(self):
128168725dc8SNiels Provos        codearrayadd = self._entry.CodeArrayAdd(
1282f0ded5f3SAzat Khuzhin            "msg->%(name)s_data[msg->%(name)s_length - 1]" % self.GetTranslation(),
1283f0ded5f3SAzat Khuzhin            "value",
1284f0ded5f3SAzat Khuzhin        )
12857e3a7af7SNiels Provos        code = [
1286f0ded5f3SAzat Khuzhin            "static int",
1287f0ded5f3SAzat Khuzhin            "%(parent_name)s_%(name)s_expand_to_hold_more("
1288f0ded5f3SAzat Khuzhin            "struct %(parent_name)s *msg)",
1289f0ded5f3SAzat Khuzhin            "{",
1290f0ded5f3SAzat Khuzhin            "  int tobe_allocated = msg->%(name)s_num_allocated;",
1291f0ded5f3SAzat Khuzhin            "  %(ctype)s* new_data = NULL;",
1292f0ded5f3SAzat Khuzhin            "  tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;",
1293f0ded5f3SAzat Khuzhin            "  new_data = (%(ctype)s*) realloc(msg->%(name)s_data,",
1294f0ded5f3SAzat Khuzhin            "      tobe_allocated * sizeof(%(ctype)s));",
1295f0ded5f3SAzat Khuzhin            "  if (new_data == NULL)",
1296f0ded5f3SAzat Khuzhin            "    return -1;",
1297f0ded5f3SAzat Khuzhin            "  msg->%(name)s_data = new_data;",
1298f0ded5f3SAzat Khuzhin            "  msg->%(name)s_num_allocated = tobe_allocated;",
1299f0ded5f3SAzat Khuzhin            "  return 0;",
1300f0ded5f3SAzat Khuzhin            "}",
1301f0ded5f3SAzat Khuzhin            "",
1302f0ded5f3SAzat Khuzhin            "%(ctype)s %(optpointer)s",
1303f0ded5f3SAzat Khuzhin            "%(parent_name)s_%(name)s_add(struct %(parent_name)s *msg%(optaddarg)s)",
1304f0ded5f3SAzat Khuzhin            "{",
1305f0ded5f3SAzat Khuzhin            "  if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {",
1306f0ded5f3SAzat Khuzhin            "    if (%(parent_name)s_%(name)s_expand_to_hold_more(msg)<0)",
1307f0ded5f3SAzat Khuzhin            "      goto error;",
1308f0ded5f3SAzat Khuzhin            "  }",
1309f0ded5f3SAzat Khuzhin        ]
13103c1a6a68SNiels Provos
13117e3a7af7SNiels Provos        code = TranslateList(code, self.GetTranslation())
13127e3a7af7SNiels Provos
1313f0ded5f3SAzat Khuzhin        code += ["  " + x for x in codearrayadd]
13147e3a7af7SNiels Provos
1315f0ded5f3SAzat Khuzhin        code += TranslateList(
1316f0ded5f3SAzat Khuzhin            [
1317f0ded5f3SAzat Khuzhin                "  msg->%(name)s_set = 1;",
1318f0ded5f3SAzat Khuzhin                "  return %(optreference)s(msg->%(name)s_data["
1319f0ded5f3SAzat Khuzhin                "msg->%(name)s_length - 1]);",
1320f0ded5f3SAzat Khuzhin                "error:",
1321f0ded5f3SAzat Khuzhin                "  --msg->%(name)s_length;",
1322f0ded5f3SAzat Khuzhin                "  return (NULL);",
1323f0ded5f3SAzat Khuzhin                "}",
1324f0ded5f3SAzat Khuzhin            ],
1325f0ded5f3SAzat Khuzhin            self.GetTranslation(),
1326f0ded5f3SAzat Khuzhin        )
13277e3a7af7SNiels Provos
13287e3a7af7SNiels Provos        return code
1329b4ab56dcSNiels Provos
133068725dc8SNiels Provos    def CodeComplete(self, structname, var_name):
1331f0ded5f3SAzat Khuzhin        self._index = "i"
133268725dc8SNiels Provos        tmp = self._entry.CodeComplete(structname, self._entry.GetVarName(var_name))
133368725dc8SNiels Provos        # skip the whole loop if there is nothing to check
133468725dc8SNiels Provos        if not tmp:
133568725dc8SNiels Provos            return []
1336b4ab56dcSNiels Provos
1337f0ded5f3SAzat Khuzhin        translate = self.GetTranslation({"structname": structname})
133868725dc8SNiels Provos        code = [
1339f0ded5f3SAzat Khuzhin            "{",
1340f0ded5f3SAzat Khuzhin            "  int i;",
1341f0ded5f3SAzat Khuzhin            "  for (i = 0; i < %(structname)s->%(name)s_length; ++i) {",
1342f0ded5f3SAzat Khuzhin        ]
13433c1a6a68SNiels Provos
134468725dc8SNiels Provos        code = TranslateList(code, translate)
134568725dc8SNiels Provos
1346f0ded5f3SAzat Khuzhin        code += ["    " + x for x in tmp]
134768725dc8SNiels Provos
1348f0ded5f3SAzat Khuzhin        code += ["  }", "}"]
1349b4ab56dcSNiels Provos
1350b4ab56dcSNiels Provos        return code
1351b4ab56dcSNiels Provos
1352f0ded5f3SAzat Khuzhin    def CodeUnmarshal(self, buf, tag_name, var_name, _var_len):
1353f0ded5f3SAzat Khuzhin        translate = self.GetTranslation(
1354f0ded5f3SAzat Khuzhin            {
1355f0ded5f3SAzat Khuzhin                "var": var_name,
1356f0ded5f3SAzat Khuzhin                "buf": buf,
1357f0ded5f3SAzat Khuzhin                "tag": tag_name,
1358f0ded5f3SAzat Khuzhin                "init": self._entry.GetInitializer(),
1359f0ded5f3SAzat Khuzhin            }
1360f0ded5f3SAzat Khuzhin        )
136168725dc8SNiels Provos        code = [
1362f0ded5f3SAzat Khuzhin            "if (%(var)s->%(name)s_length >= %(var)s->%(name)s_num_allocated &&",
1363f0ded5f3SAzat Khuzhin            "    %(parent_name)s_%(name)s_expand_to_hold_more(%(var)s) < 0) {",
1364f6ab2a28SNick Mathewson            '  puts("HEY NOW");',
1365f0ded5f3SAzat Khuzhin            "  return (-1);",
1366f0ded5f3SAzat Khuzhin            "}",
1367f0ded5f3SAzat Khuzhin        ]
13683c1a6a68SNiels Provos
136968725dc8SNiels Provos        # the unmarshal code directly returns
137068725dc8SNiels Provos        code = TranslateList(code, translate)
1371b4ab56dcSNiels Provos
1372f0ded5f3SAzat Khuzhin        self._index = "%(var)s->%(name)s_length" % translate
1373f0ded5f3SAzat Khuzhin        code += self._entry.CodeUnmarshal(
1374f0ded5f3SAzat Khuzhin            buf,
1375f0ded5f3SAzat Khuzhin            tag_name,
137668725dc8SNiels Provos            self._entry.GetVarName(var_name),
1377f0ded5f3SAzat Khuzhin            self._entry.GetVarLen(var_name),
1378f0ded5f3SAzat Khuzhin        )
137968725dc8SNiels Provos
1380f0ded5f3SAzat Khuzhin        code += ["++%(var)s->%(name)s_length;" % translate]
138168725dc8SNiels Provos
138268725dc8SNiels Provos        return code
138368725dc8SNiels Provos
1384f0ded5f3SAzat Khuzhin    def CodeMarshal(self, buf, tag_name, var_name, _var_len):
1385f0ded5f3SAzat Khuzhin        code = ["{", "  int i;", "  for (i = 0; i < %(var)s->%(name)s_length; ++i) {"]
138668725dc8SNiels Provos
1387f0ded5f3SAzat Khuzhin        self._index = "i"
1388f0ded5f3SAzat Khuzhin        code += self._entry.CodeMarshal(
1389f0ded5f3SAzat Khuzhin            buf,
1390f0ded5f3SAzat Khuzhin            tag_name,
139168725dc8SNiels Provos            self._entry.GetVarName(var_name),
1392f0ded5f3SAzat Khuzhin            self._entry.GetVarLen(var_name),
1393f0ded5f3SAzat Khuzhin        )
1394f0ded5f3SAzat Khuzhin        code += ["  }", "}"]
139568725dc8SNiels Provos
1396f0ded5f3SAzat Khuzhin        code = "\n".join(code) % self.GetTranslation({"var": var_name})
139768725dc8SNiels Provos
1398f0ded5f3SAzat Khuzhin        return code.split("\n")
1399b4ab56dcSNiels Provos
1400b4ab56dcSNiels Provos    def CodeClear(self, structname):
1401f0ded5f3SAzat Khuzhin        translate = self.GetTranslation({"structname": structname})
140268725dc8SNiels Provos        codearrayfree = self._entry.CodeArrayFree(
1403f0ded5f3SAzat Khuzhin            "%(structname)s->%(name)s_data[i]"
1404f0ded5f3SAzat Khuzhin            % self.GetTranslation({"structname": structname})
1405f0ded5f3SAzat Khuzhin        )
14067e3a7af7SNiels Provos
1407f0ded5f3SAzat Khuzhin        code = ["if (%(structname)s->%(name)s_set == 1) {"]
14087e3a7af7SNiels Provos
14097e3a7af7SNiels Provos        if codearrayfree:
14107e3a7af7SNiels Provos            code += [
1411f0ded5f3SAzat Khuzhin                "  int i;",
1412f0ded5f3SAzat Khuzhin                "  for (i = 0; i < %(structname)s->%(name)s_length; ++i) {",
1413f0ded5f3SAzat Khuzhin            ]
14147e3a7af7SNiels Provos
14157e3a7af7SNiels Provos        code = TranslateList(code, translate)
14167e3a7af7SNiels Provos
14177e3a7af7SNiels Provos        if codearrayfree:
1418f0ded5f3SAzat Khuzhin            code += ["    " + x for x in codearrayfree]
1419f0ded5f3SAzat Khuzhin            code += ["  }"]
14207e3a7af7SNiels Provos
1421f0ded5f3SAzat Khuzhin        code += TranslateList(
1422f0ded5f3SAzat Khuzhin            [
1423f0ded5f3SAzat Khuzhin                "  free(%(structname)s->%(name)s_data);",
1424f0ded5f3SAzat Khuzhin                "  %(structname)s->%(name)s_data = NULL;",
1425f0ded5f3SAzat Khuzhin                "  %(structname)s->%(name)s_set = 0;",
1426f0ded5f3SAzat Khuzhin                "  %(structname)s->%(name)s_length = 0;",
1427f0ded5f3SAzat Khuzhin                "  %(structname)s->%(name)s_num_allocated = 0;",
1428f0ded5f3SAzat Khuzhin                "}",
1429f0ded5f3SAzat Khuzhin            ],
1430f0ded5f3SAzat Khuzhin            translate,
1431f0ded5f3SAzat Khuzhin        )
143268725dc8SNiels Provos
1433b4ab56dcSNiels Provos        return code
1434b4ab56dcSNiels Provos
143568725dc8SNiels Provos    def CodeInitialize(self, name):
1436f0ded5f3SAzat Khuzhin        code = [
1437f0ded5f3SAzat Khuzhin            "%s->%s_data = NULL;" % (name, self._name),
1438f0ded5f3SAzat Khuzhin            "%s->%s_length = 0;" % (name, self._name),
1439f0ded5f3SAzat Khuzhin            "%s->%s_num_allocated = 0;" % (name, self._name),
1440f0ded5f3SAzat Khuzhin        ]
1441b4ab56dcSNiels Provos        return code
1442b4ab56dcSNiels Provos
144368725dc8SNiels Provos    def CodeFree(self, structname):
1444f0ded5f3SAzat Khuzhin        code = self.CodeClear(structname)
144568725dc8SNiels Provos
1446f0ded5f3SAzat Khuzhin        code += TranslateList(
1447f0ded5f3SAzat Khuzhin            ["free(%(structname)s->%(name)s_data);"],
1448f0ded5f3SAzat Khuzhin            self.GetTranslation({"structname": structname}),
1449f0ded5f3SAzat Khuzhin        )
145068725dc8SNiels Provos
14517e3a7af7SNiels Provos        return code
1452b4ab56dcSNiels Provos
1453b4ab56dcSNiels Provos    def Declaration(self):
1454f0ded5f3SAzat Khuzhin        dcl = [
1455f0ded5f3SAzat Khuzhin            "%s *%s_data;" % (self._ctype, self._name),
1456f0ded5f3SAzat Khuzhin            "int %s_length;" % self._name,
1457f0ded5f3SAzat Khuzhin            "int %s_num_allocated;" % self._name,
1458f0ded5f3SAzat Khuzhin        ]
1459b4ab56dcSNiels Provos
1460b4ab56dcSNiels Provos        return dcl
1461b4ab56dcSNiels Provos
1462949cbd12SNiels Provos
1463f0ded5f3SAzat Khuzhindef NormalizeLine(line):
1464f0ded5f3SAzat Khuzhin
1465f0ded5f3SAzat Khuzhin    line = CPPCOMMENT_RE.sub("", line)
1466226fd50aSNiels Provos    line = line.strip()
1467f0ded5f3SAzat Khuzhin    line = WHITESPACE_RE.sub(" ", line)
1468949cbd12SNiels Provos
1469949cbd12SNiels Provos    return line
1470949cbd12SNiels Provos
1471f0ded5f3SAzat Khuzhin
1472f0ded5f3SAzat KhuzhinENTRY_NAME_RE = re.compile(r"(?P<name>[^\[\]]+)(\[(?P<fixed_length>.*)\])?")
1473f0ded5f3SAzat KhuzhinENTRY_TAG_NUMBER_RE = re.compile(r"(0x)?\d+", re.I)
1474f0ded5f3SAzat Khuzhin
1475f0ded5f3SAzat Khuzhin
1476a7e39551SNiels Provosdef ProcessOneEntry(factory, newstruct, entry):
1477f0ded5f3SAzat Khuzhin    optional = False
1478f0ded5f3SAzat Khuzhin    array = False
1479f0ded5f3SAzat Khuzhin    entry_type = ""
1480f0ded5f3SAzat Khuzhin    name = ""
1481f0ded5f3SAzat Khuzhin    tag = ""
1482949cbd12SNiels Provos    tag_set = None
1483f0ded5f3SAzat Khuzhin    separator = ""
1484f0ded5f3SAzat Khuzhin    fixed_length = ""
1485949cbd12SNiels Provos
1486f0ded5f3SAzat Khuzhin    for token in entry.split(" "):
1487226fd50aSNiels Provos        if not entry_type:
1488f0ded5f3SAzat Khuzhin            if not optional and token == "optional":
1489f0ded5f3SAzat Khuzhin                optional = True
1490949cbd12SNiels Provos                continue
1491949cbd12SNiels Provos
1492f0ded5f3SAzat Khuzhin            if not array and token == "array":
1493f0ded5f3SAzat Khuzhin                array = True
1494949cbd12SNiels Provos                continue
1495949cbd12SNiels Provos
1496226fd50aSNiels Provos        if not entry_type:
1497226fd50aSNiels Provos            entry_type = token
1498949cbd12SNiels Provos            continue
1499949cbd12SNiels Provos
1500949cbd12SNiels Provos        if not name:
1501f0ded5f3SAzat Khuzhin            res = ENTRY_NAME_RE.match(token)
1502949cbd12SNiels Provos            if not res:
150337d3e16cSNiels Provos                raise RpcGenError(
1504f0ded5f3SAzat Khuzhin                    r"""Cannot parse name: "%s" around line %d""" % (entry, LINE_COUNT)
1505f0ded5f3SAzat Khuzhin                )
1506f0ded5f3SAzat Khuzhin            name = res.group("name")
1507f0ded5f3SAzat Khuzhin            fixed_length = res.group("fixed_length")
1508949cbd12SNiels Provos            continue
1509949cbd12SNiels Provos
1510949cbd12SNiels Provos        if not separator:
1511949cbd12SNiels Provos            separator = token
1512f0ded5f3SAzat Khuzhin            if separator != "=":
1513f0ded5f3SAzat Khuzhin                raise RpcGenError(
1514f0ded5f3SAzat Khuzhin                    r'''Expected "=" after name "%s" got "%s"''' % (name, token)
1515f0ded5f3SAzat Khuzhin                )
1516949cbd12SNiels Provos            continue
1517949cbd12SNiels Provos
1518949cbd12SNiels Provos        if not tag_set:
1519949cbd12SNiels Provos            tag_set = 1
1520f0ded5f3SAzat Khuzhin            if not ENTRY_TAG_NUMBER_RE.match(token):
1521f0ded5f3SAzat Khuzhin                raise RpcGenError(r'''Expected tag number: "%s"''' % (entry))
1522ba487199SNiels Provos            tag = int(token, 0)
1523949cbd12SNiels Provos            continue
1524949cbd12SNiels Provos
1525f0ded5f3SAzat Khuzhin        raise RpcGenError(r'''Cannot parse "%s"''' % (entry))
1526949cbd12SNiels Provos
1527949cbd12SNiels Provos    if not tag_set:
1528f0ded5f3SAzat Khuzhin        raise RpcGenError(r'''Need tag number: "%s"''' % (entry))
1529949cbd12SNiels Provos
1530949cbd12SNiels Provos    # Create the right entry
1531f0ded5f3SAzat Khuzhin    if entry_type == "bytes":
1532949cbd12SNiels Provos        if fixed_length:
1533a7e39551SNiels Provos            newentry = factory.EntryBytes(entry_type, name, tag, fixed_length)
1534949cbd12SNiels Provos        else:
1535a7e39551SNiels Provos            newentry = factory.EntryVarBytes(entry_type, name, tag)
1536f0ded5f3SAzat Khuzhin    elif entry_type == "int" and not fixed_length:
1537a7e39551SNiels Provos        newentry = factory.EntryInt(entry_type, name, tag)
1538f0ded5f3SAzat Khuzhin    elif entry_type == "int64" and not fixed_length:
153999a1063eSNiels Provos        newentry = factory.EntryInt(entry_type, name, tag, bits=64)
1540f0ded5f3SAzat Khuzhin    elif entry_type == "string" and not fixed_length:
1541a7e39551SNiels Provos        newentry = factory.EntryString(entry_type, name, tag)
1542949cbd12SNiels Provos    else:
1543f0ded5f3SAzat Khuzhin        res = STRUCT_REF_RE.match(entry_type)
1544949cbd12SNiels Provos        if res:
1545949cbd12SNiels Provos            # References another struct defined in our file
1546f0ded5f3SAzat Khuzhin            newentry = factory.EntryStruct(entry_type, name, tag, res.group("name"))
1547949cbd12SNiels Provos        else:
154837d3e16cSNiels Provos            raise RpcGenError('Bad type: "%s" in "%s"' % (entry_type, entry))
1549949cbd12SNiels Provos
1550b4ab56dcSNiels Provos    structs = []
1551b4ab56dcSNiels Provos
1552949cbd12SNiels Provos    if optional:
1553949cbd12SNiels Provos        newentry.MakeOptional()
1554949cbd12SNiels Provos    if array:
1555949cbd12SNiels Provos        newentry.MakeArray()
1556949cbd12SNiels Provos
1557949cbd12SNiels Provos    newentry.SetStruct(newstruct)
1558f0ded5f3SAzat Khuzhin    newentry.SetLineCount(LINE_COUNT)
1559949cbd12SNiels Provos    newentry.Verify()
1560949cbd12SNiels Provos
1561b4ab56dcSNiels Provos    if array:
1562b4ab56dcSNiels Provos        # We need to encapsulate this entry into a struct
1563812d2fd8SNiels Provos        newentry = factory.EntryArray(newentry)
1564b4ab56dcSNiels Provos        newentry.SetStruct(newstruct)
1565f0ded5f3SAzat Khuzhin        newentry.SetLineCount(LINE_COUNT)
1566b4ab56dcSNiels Provos        newentry.MakeArray()
1567b4ab56dcSNiels Provos
1568949cbd12SNiels Provos    newstruct.AddEntry(newentry)
1569949cbd12SNiels Provos
1570b4ab56dcSNiels Provos    return structs
1571b4ab56dcSNiels Provos
1572f0ded5f3SAzat Khuzhin
1573a7e39551SNiels Provosdef ProcessStruct(factory, data):
1574f0ded5f3SAzat Khuzhin    tokens = data.split(" ")
1575949cbd12SNiels Provos
1576949cbd12SNiels Provos    # First three tokens are: 'struct' 'name' '{'
1577a7e39551SNiels Provos    newstruct = factory.Struct(tokens[1])
1578949cbd12SNiels Provos
1579f0ded5f3SAzat Khuzhin    inside = " ".join(tokens[3:-1])
1580949cbd12SNiels Provos
1581f0ded5f3SAzat Khuzhin    tokens = inside.split(";")
1582949cbd12SNiels Provos
1583b4ab56dcSNiels Provos    structs = []
1584b4ab56dcSNiels Provos
1585949cbd12SNiels Provos    for entry in tokens:
1586949cbd12SNiels Provos        entry = NormalizeLine(entry)
1587949cbd12SNiels Provos        if not entry:
1588949cbd12SNiels Provos            continue
1589949cbd12SNiels Provos
1590b4ab56dcSNiels Provos        # It's possible that new structs get defined in here
1591a7e39551SNiels Provos        structs.extend(ProcessOneEntry(factory, newstruct, entry))
1592949cbd12SNiels Provos
1593b4ab56dcSNiels Provos    structs.append(newstruct)
1594b4ab56dcSNiels Provos    return structs
1595949cbd12SNiels Provos
1596949cbd12SNiels Provos
1597f0ded5f3SAzat KhuzhinC_COMMENT_START = "/*"
1598f0ded5f3SAzat KhuzhinC_COMMENT_END = "*/"
1599949cbd12SNiels Provos
1600f0ded5f3SAzat KhuzhinC_COMMENT_START_RE = re.compile(re.escape(C_COMMENT_START))
1601f0ded5f3SAzat KhuzhinC_COMMENT_END_RE = re.compile(re.escape(C_COMMENT_END))
1602c4e60994SNiels Provos
1603f0ded5f3SAzat KhuzhinC_COMMENT_START_SUB_RE = re.compile(r"%s.*$" % (re.escape(C_COMMENT_START)))
1604f0ded5f3SAzat KhuzhinC_COMMENT_END_SUB_RE = re.compile(r"%s.*$" % (re.escape(C_COMMENT_END)))
1605f0ded5f3SAzat Khuzhin
1606f0ded5f3SAzat KhuzhinC_MULTILINE_COMMENT_SUB_RE = re.compile(
1607f0ded5f3SAzat Khuzhin    r"%s.*?%s" % (re.escape(C_COMMENT_START), re.escape(C_COMMENT_END))
1608f0ded5f3SAzat Khuzhin)
1609f0ded5f3SAzat KhuzhinCPP_CONDITIONAL_BLOCK_RE = re.compile(r"#(if( |def)|endif)")
1610f0ded5f3SAzat KhuzhinINCLUDE_RE = re.compile(r'#include (".+"|<.+>)')
1611f0ded5f3SAzat Khuzhin
1612f0ded5f3SAzat Khuzhin
1613f0ded5f3SAzat Khuzhindef GetNextStruct(filep):
1614f0ded5f3SAzat Khuzhin    global CPP_DIRECT
1615f0ded5f3SAzat Khuzhin    global LINE_COUNT
1616f0ded5f3SAzat Khuzhin
1617f0ded5f3SAzat Khuzhin    got_struct = False
1618f0ded5f3SAzat Khuzhin    have_c_comment = False
1619f0ded5f3SAzat Khuzhin
1620f0ded5f3SAzat Khuzhin    data = ""
1621f0ded5f3SAzat Khuzhin
1622f0ded5f3SAzat Khuzhin    while True:
1623f0ded5f3SAzat Khuzhin        line = filep.readline()
16243a15f7d4SNiels Provos        if not line:
16253a15f7d4SNiels Provos            break
16263a15f7d4SNiels Provos
1627f0ded5f3SAzat Khuzhin        LINE_COUNT += 1
1628949cbd12SNiels Provos        line = line[:-1]
1629c4e60994SNiels Provos
1630f0ded5f3SAzat Khuzhin        if not have_c_comment and C_COMMENT_START_RE.search(line):
1631f0ded5f3SAzat Khuzhin            if C_MULTILINE_COMMENT_SUB_RE.search(line):
1632f0ded5f3SAzat Khuzhin                line = C_MULTILINE_COMMENT_SUB_RE.sub("", line)
1633c4e60994SNiels Provos            else:
1634f0ded5f3SAzat Khuzhin                line = C_COMMENT_START_SUB_RE.sub("", line)
1635f0ded5f3SAzat Khuzhin                have_c_comment = True
1636c4e60994SNiels Provos
1637c4e60994SNiels Provos        if have_c_comment:
1638f0ded5f3SAzat Khuzhin            if not C_COMMENT_END_RE.search(line):
1639c4e60994SNiels Provos                continue
1640f0ded5f3SAzat Khuzhin            have_c_comment = False
1641f0ded5f3SAzat Khuzhin            line = C_COMMENT_END_SUB_RE.sub("", line)
1642c4e60994SNiels Provos
1643949cbd12SNiels Provos        line = NormalizeLine(line)
1644949cbd12SNiels Provos
1645949cbd12SNiels Provos        if not line:
1646949cbd12SNiels Provos            continue
1647949cbd12SNiels Provos
1648949cbd12SNiels Provos        if not got_struct:
1649f0ded5f3SAzat Khuzhin            if INCLUDE_RE.match(line):
1650f0ded5f3SAzat Khuzhin                CPP_DIRECT.append(line)
1651f0ded5f3SAzat Khuzhin            elif CPP_CONDITIONAL_BLOCK_RE.match(line):
1652f0ded5f3SAzat Khuzhin                CPP_DIRECT.append(line)
1653f0ded5f3SAzat Khuzhin            elif PREPROCESSOR_DEF_RE.match(line):
1654f0ded5f3SAzat Khuzhin                HEADER_DIRECT.append(line)
1655f0ded5f3SAzat Khuzhin            elif not STRUCT_DEF_RE.match(line):
1656f0ded5f3SAzat Khuzhin                raise RpcGenError("Missing struct on line %d: %s" % (LINE_COUNT, line))
1657949cbd12SNiels Provos            else:
1658f0ded5f3SAzat Khuzhin                got_struct = True
1659949cbd12SNiels Provos                data += line
1660949cbd12SNiels Provos            continue
1661949cbd12SNiels Provos
1662949cbd12SNiels Provos        # We are inside the struct
1663f0ded5f3SAzat Khuzhin        tokens = line.split("}")
1664949cbd12SNiels Provos        if len(tokens) == 1:
1665f0ded5f3SAzat Khuzhin            data += " " + line
1666949cbd12SNiels Provos            continue
1667949cbd12SNiels Provos
1668f0ded5f3SAzat Khuzhin        if tokens[1]:
1669f0ded5f3SAzat Khuzhin            raise RpcGenError("Trailing garbage after struct on line %d" % LINE_COUNT)
1670949cbd12SNiels Provos
1671949cbd12SNiels Provos        # We found the end of the struct
1672f0ded5f3SAzat Khuzhin        data += " %s}" % tokens[0]
1673949cbd12SNiels Provos        break
1674949cbd12SNiels Provos
1675949cbd12SNiels Provos    # Remove any comments, that might be in there
1676f0ded5f3SAzat Khuzhin    data = re.sub(r"/\*.*\*/", "", data)
1677949cbd12SNiels Provos
1678949cbd12SNiels Provos    return data
1679949cbd12SNiels Provos
1680949cbd12SNiels Provos
1681f0ded5f3SAzat Khuzhindef Parse(factory, filep):
16823a15f7d4SNiels Provos    """
16833a15f7d4SNiels Provos    Parses the input file and returns C code and corresponding header file.
16843a15f7d4SNiels Provos    """
1685949cbd12SNiels Provos
1686949cbd12SNiels Provos    entities = []
1687949cbd12SNiels Provos
1688949cbd12SNiels Provos    while 1:
1689949cbd12SNiels Provos        # Just gets the whole struct nicely formatted
1690f0ded5f3SAzat Khuzhin        data = GetNextStruct(filep)
1691949cbd12SNiels Provos
1692949cbd12SNiels Provos        if not data:
1693949cbd12SNiels Provos            break
1694949cbd12SNiels Provos
1695a7e39551SNiels Provos        entities.extend(ProcessStruct(factory, data))
1696949cbd12SNiels Provos
1697949cbd12SNiels Provos    return entities
1698949cbd12SNiels Provos
1699f0ded5f3SAzat Khuzhin
1700*48e04887SEnji Cooperclass CCodeGenerator(object):
1701a7e39551SNiels Provos    def __init__(self):
1702a7e39551SNiels Provos        pass
1703a7e39551SNiels Provos
1704f0ded5f3SAzat Khuzhin    @staticmethod
1705f0ded5f3SAzat Khuzhin    def GuardName(name):
1706bbcc54efSNiels Provos        # Use the complete provided path to the input file, with all
1707bbcc54efSNiels Provos        # non-identifier characters replaced with underscores, to
1708bbcc54efSNiels Provos        # reduce the chance of a collision between guard macros.
1709f0ded5f3SAzat Khuzhin        return "EVENT_RPCOUT_%s_" % (NONIDENT_RE.sub("_", name).upper())
1710949cbd12SNiels Provos
1711a7e39551SNiels Provos    def HeaderPreamble(self, name):
1712a7e39551SNiels Provos        guard = self.GuardName(name)
1713f0ded5f3SAzat Khuzhin        pre = """
1714f0ded5f3SAzat Khuzhin/*
1715f0ded5f3SAzat Khuzhin * Automatically generated from %s
1716f0ded5f3SAzat Khuzhin */
1717c1aa5480SNiels Provos
1718f0ded5f3SAzat Khuzhin#ifndef %s
1719f0ded5f3SAzat Khuzhin#define %s
1720c1aa5480SNiels Provos
1721f0ded5f3SAzat Khuzhin""" % (
1722f0ded5f3SAzat Khuzhin            name,
1723f0ded5f3SAzat Khuzhin            guard,
1724f0ded5f3SAzat Khuzhin            guard,
1725bbcc54efSNiels Provos        )
1726949cbd12SNiels Provos
1727f0ded5f3SAzat Khuzhin        if HEADER_DIRECT:
1728f0ded5f3SAzat Khuzhin            for statement in HEADER_DIRECT:
1729f0ded5f3SAzat Khuzhin                pre += "%s\n" % statement
1730f0ded5f3SAzat Khuzhin            pre += "\n"
1731f0ded5f3SAzat Khuzhin
1732f0ded5f3SAzat Khuzhin        pre += """
1733f0ded5f3SAzat Khuzhin#include <event2/util.h> /* for ev_uint*_t */
1734f0ded5f3SAzat Khuzhin#include <event2/rpc.h>
1735f0ded5f3SAzat Khuzhin"""
1736f0ded5f3SAzat Khuzhin
1737949cbd12SNiels Provos        return pre
1738949cbd12SNiels Provos
1739a7e39551SNiels Provos    def HeaderPostamble(self, name):
1740a7e39551SNiels Provos        guard = self.GuardName(name)
1741f0ded5f3SAzat Khuzhin        return "#endif  /* %s */" % (guard)
1742949cbd12SNiels Provos
1743f0ded5f3SAzat Khuzhin    @staticmethod
1744f0ded5f3SAzat Khuzhin    def BodyPreamble(name, header_file):
1745949cbd12SNiels Provos        global _NAME
1746949cbd12SNiels Provos        global _VERSION
1747949cbd12SNiels Provos
1748f0ded5f3SAzat Khuzhin        slash = header_file.rfind("/")
1749bbcc54efSNiels Provos        if slash != -1:
1750bbcc54efSNiels Provos            header_file = header_file[slash + 1 :]
1751949cbd12SNiels Provos
1752f0ded5f3SAzat Khuzhin        pre = """
1753f0ded5f3SAzat Khuzhin/*
1754f0ded5f3SAzat Khuzhin * Automatically generated from %(name)s
1755f0ded5f3SAzat Khuzhin * by %(script_name)s/%(script_version)s.  DO NOT EDIT THIS FILE.
1756f0ded5f3SAzat Khuzhin */
1757949cbd12SNiels Provos
1758f0ded5f3SAzat Khuzhin#include <stdlib.h>
1759f0ded5f3SAzat Khuzhin#include <string.h>
1760f0ded5f3SAzat Khuzhin#include <assert.h>
1761f0ded5f3SAzat Khuzhin#include <event2/event-config.h>
1762f0ded5f3SAzat Khuzhin#include <event2/event.h>
1763f0ded5f3SAzat Khuzhin#include <event2/buffer.h>
1764f0ded5f3SAzat Khuzhin#include <event2/tag.h>
1765f0ded5f3SAzat Khuzhin
1766f0ded5f3SAzat Khuzhin#if defined(EVENT__HAVE___func__)
1767f0ded5f3SAzat Khuzhin# ifndef __func__
1768f0ded5f3SAzat Khuzhin#  define __func__ __func__
1769f0ded5f3SAzat Khuzhin# endif
1770f0ded5f3SAzat Khuzhin#elif defined(EVENT__HAVE___FUNCTION__)
1771f0ded5f3SAzat Khuzhin# define __func__ __FUNCTION__
1772f0ded5f3SAzat Khuzhin#else
1773f0ded5f3SAzat Khuzhin# define __func__ __FILE__
1774f0ded5f3SAzat Khuzhin#endif
1775f0ded5f3SAzat Khuzhin
1776f0ded5f3SAzat Khuzhin""" % {
1777f0ded5f3SAzat Khuzhin            "name": name,
1778f0ded5f3SAzat Khuzhin            "script_name": _NAME,
1779f0ded5f3SAzat Khuzhin            "script_version": _VERSION,
1780f0ded5f3SAzat Khuzhin        }
1781f0ded5f3SAzat Khuzhin
1782f0ded5f3SAzat Khuzhin        for statement in CPP_DIRECT:
1783f0ded5f3SAzat Khuzhin            pre += "%s\n" % statement
1784949cbd12SNiels Provos
1785949cbd12SNiels Provos        pre += '\n#include "%s"\n\n' % header_file
1786949cbd12SNiels Provos
1787f0ded5f3SAzat Khuzhin        pre += "void event_warn(const char *fmt, ...);\n"
1788f0ded5f3SAzat Khuzhin        pre += "void event_warnx(const char *fmt, ...);\n\n"
1789e5ab86a7SNiels Provos
1790949cbd12SNiels Provos        return pre
1791949cbd12SNiels Provos
1792f0ded5f3SAzat Khuzhin    @staticmethod
1793f0ded5f3SAzat Khuzhin    def HeaderFilename(filename):
1794f0ded5f3SAzat Khuzhin        return ".".join(filename.split(".")[:-1]) + ".h"
1795226fd50aSNiels Provos
1796f0ded5f3SAzat Khuzhin    @staticmethod
1797f0ded5f3SAzat Khuzhin    def CodeFilename(filename):
1798f0ded5f3SAzat Khuzhin        return ".".join(filename.split(".")[:-1]) + ".gen.c"
1799949cbd12SNiels Provos
1800f0ded5f3SAzat Khuzhin    @staticmethod
1801f0ded5f3SAzat Khuzhin    def Struct(name):
1802a7e39551SNiels Provos        return StructCCode(name)
1803a7e39551SNiels Provos
1804f0ded5f3SAzat Khuzhin    @staticmethod
1805f0ded5f3SAzat Khuzhin    def EntryBytes(entry_type, name, tag, fixed_length):
1806a7e39551SNiels Provos        return EntryBytes(entry_type, name, tag, fixed_length)
1807a7e39551SNiels Provos
1808f0ded5f3SAzat Khuzhin    @staticmethod
1809f0ded5f3SAzat Khuzhin    def EntryVarBytes(entry_type, name, tag):
1810a7e39551SNiels Provos        return EntryVarBytes(entry_type, name, tag)
1811a7e39551SNiels Provos
1812f0ded5f3SAzat Khuzhin    @staticmethod
1813f0ded5f3SAzat Khuzhin    def EntryInt(entry_type, name, tag, bits=32):
181499a1063eSNiels Provos        return EntryInt(entry_type, name, tag, bits)
1815a7e39551SNiels Provos
1816f0ded5f3SAzat Khuzhin    @staticmethod
1817f0ded5f3SAzat Khuzhin    def EntryString(entry_type, name, tag):
1818a7e39551SNiels Provos        return EntryString(entry_type, name, tag)
1819a7e39551SNiels Provos
1820f0ded5f3SAzat Khuzhin    @staticmethod
1821f0ded5f3SAzat Khuzhin    def EntryStruct(entry_type, name, tag, struct_name):
1822a7e39551SNiels Provos        return EntryStruct(entry_type, name, tag, struct_name)
1823a7e39551SNiels Provos
1824f0ded5f3SAzat Khuzhin    @staticmethod
1825f0ded5f3SAzat Khuzhin    def EntryArray(entry):
1826812d2fd8SNiels Provos        return EntryArray(entry)
1827812d2fd8SNiels Provos
1828fbb181d1SNiels Provos
1829*48e04887SEnji Cooperclass CommandLine(object):
1830f0ded5f3SAzat Khuzhin    def __init__(self, argv=None):
1831f1250eb6SNick Mathewson        """Initialize a command-line to launch event_rpcgen, as if
1832f1250eb6SNick Mathewson           from a command-line with CommandLine(sys.argv).  If you're
1833f1250eb6SNick Mathewson           calling this directly, remember to provide a dummy value
1834f1250eb6SNick Mathewson           for sys.argv[0]
1835f1250eb6SNick Mathewson        """
1836f0ded5f3SAzat Khuzhin        global QUIETLY
1837f0ded5f3SAzat Khuzhin
1838fbb181d1SNiels Provos        self.filename = None
1839fbb181d1SNiels Provos        self.header_file = None
1840fbb181d1SNiels Provos        self.impl_file = None
1841fbb181d1SNiels Provos        self.factory = CCodeGenerator()
1842fbb181d1SNiels Provos
1843f0ded5f3SAzat Khuzhin        parser = argparse.ArgumentParser(
1844f0ded5f3SAzat Khuzhin            usage="%(prog)s [options] rpc-file [[h-file] c-file]"
1845f0ded5f3SAzat Khuzhin        )
1846f0ded5f3SAzat Khuzhin        parser.add_argument("--quiet", action="store_true", default=False)
1847f0ded5f3SAzat Khuzhin        parser.add_argument("rpc_file", type=argparse.FileType("r"))
1848aa59c1e9SNick Mathewson
1849f0ded5f3SAzat Khuzhin        args, extra_args = parser.parse_known_args(args=argv)
1850fbb181d1SNiels Provos
1851f0ded5f3SAzat Khuzhin        QUIETLY = args.quiet
1852fbb181d1SNiels Provos
1853f0ded5f3SAzat Khuzhin        if extra_args:
1854f0ded5f3SAzat Khuzhin            if len(extra_args) == 1:
1855f0ded5f3SAzat Khuzhin                self.impl_file = extra_args[0].replace("\\", "/")
1856f0ded5f3SAzat Khuzhin            elif len(extra_args) == 2:
1857f0ded5f3SAzat Khuzhin                self.header_file = extra_args[0].replace("\\", "/")
1858f0ded5f3SAzat Khuzhin                self.impl_file = extra_args[1].replace("\\", "/")
1859f0ded5f3SAzat Khuzhin            else:
1860f0ded5f3SAzat Khuzhin                parser.error("Spurious arguments provided")
1861f0ded5f3SAzat Khuzhin
1862f0ded5f3SAzat Khuzhin        self.rpc_file = args.rpc_file
1863fbb181d1SNiels Provos
1864fbb181d1SNiels Provos        if not self.impl_file:
1865f0ded5f3SAzat Khuzhin            self.impl_file = self.factory.CodeFilename(self.rpc_file.name)
1866fbb181d1SNiels Provos
1867fbb181d1SNiels Provos        if not self.header_file:
1868fbb181d1SNiels Provos            self.header_file = self.factory.HeaderFilename(self.impl_file)
1869fbb181d1SNiels Provos
1870f0ded5f3SAzat Khuzhin        if not self.impl_file.endswith(".c"):
1871f0ded5f3SAzat Khuzhin            parser.error("can only generate C implementation files")
1872f0ded5f3SAzat Khuzhin        if not self.header_file.endswith(".h"):
1873f0ded5f3SAzat Khuzhin            parser.error("can only generate C header files")
1874fbb181d1SNiels Provos
1875fbb181d1SNiels Provos    def run(self):
1876f0ded5f3SAzat Khuzhin        filename = self.rpc_file.name
1877fbb181d1SNiels Provos        header_file = self.header_file
1878fbb181d1SNiels Provos        impl_file = self.impl_file
1879fbb181d1SNiels Provos        factory = self.factory
1880949cbd12SNiels Provos
1881f0ded5f3SAzat Khuzhin        declare('Reading "%s"' % filename)
1882949cbd12SNiels Provos
1883f0ded5f3SAzat Khuzhin        with self.rpc_file:
1884f0ded5f3SAzat Khuzhin            entities = Parse(factory, self.rpc_file)
1885949cbd12SNiels Provos
1886aa59c1e9SNick Mathewson        declare('... creating "%s"' % header_file)
1887f0ded5f3SAzat Khuzhin        with open(header_file, "w") as header_fp:
1888532a8cc3SKiyoshi Aman            header_fp.write(factory.HeaderPreamble(filename))
1889949cbd12SNiels Provos
1890949cbd12SNiels Provos            # Create forward declarations: allows other structs to reference
1891949cbd12SNiels Provos            # each other
1892949cbd12SNiels Provos            for entry in entities:
1893949cbd12SNiels Provos                entry.PrintForwardDeclaration(header_fp)
1894f0ded5f3SAzat Khuzhin            header_fp.write("\n")
1895949cbd12SNiels Provos
1896949cbd12SNiels Provos            for entry in entities:
1897949cbd12SNiels Provos                entry.PrintTags(header_fp)
1898949cbd12SNiels Provos                entry.PrintDeclaration(header_fp)
1899532a8cc3SKiyoshi Aman            header_fp.write(factory.HeaderPostamble(filename))
1900949cbd12SNiels Provos
1901aa59c1e9SNick Mathewson        declare('... creating "%s"' % impl_file)
1902f0ded5f3SAzat Khuzhin        with open(impl_file, "w") as impl_fp:
1903532a8cc3SKiyoshi Aman            impl_fp.write(factory.BodyPreamble(filename, header_file))
1904949cbd12SNiels Provos            for entry in entities:
1905949cbd12SNiels Provos                entry.PrintCode(impl_fp)
1906949cbd12SNiels Provos
1907f0ded5f3SAzat Khuzhin
1908f0ded5f3SAzat Khuzhindef main(argv=None):
190937d3e16cSNiels Provos    try:
1910f0ded5f3SAzat Khuzhin        CommandLine(argv=argv).run()
1911f0ded5f3SAzat Khuzhin        return 0
1912532a8cc3SKiyoshi Aman    except RpcGenError as e:
1913532a8cc3SKiyoshi Aman        sys.stderr.write(e)
1914532a8cc3SKiyoshi Aman    except EnvironmentError as e:
1915fbb181d1SNiels Provos        if e.filename and e.strerror:
1916532a8cc3SKiyoshi Aman            sys.stderr.write("%s: %s" % (e.filename, e.strerror))
1917fbb181d1SNiels Provos        elif e.strerror:
1918532a8cc3SKiyoshi Aman            sys.stderr.write(e.strerror)
1919fbb181d1SNiels Provos        else:
1920fbb181d1SNiels Provos            raise
1921f0ded5f3SAzat Khuzhin    return 1
1922f0ded5f3SAzat Khuzhin
1923f0ded5f3SAzat Khuzhin
1924f0ded5f3SAzat Khuzhinif __name__ == "__main__":
1925f0ded5f3SAzat Khuzhin    sys.exit(main(argv=sys.argv[1:]))
1926