1275970Scy#!/usr/bin/env python2
2275970Scy#
3275970Scy# Copyright (c) 2005-2007 Niels Provos <provos@citi.umich.edu>
4275970Scy# Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
5275970Scy# All rights reserved.
6275970Scy#
7275970Scy# Generates marshaling code based on libevent.
8275970Scy
9275970Scy# TODO:
10275970Scy# 1) use optparse to allow the strategy shell to parse options, and
11275970Scy#    to allow the instantiated factory (for the specific output language)
12275970Scy#    to parse remaining options
13275970Scy# 2) move the globals into a class that manages execution (including the
14275970Scy#    progress outputs that space stderr at the moment)
15275970Scy# 3) emit other languages
16275970Scy
17275970Scyimport sys
18275970Scyimport re
19275970Scy
20275970Scy_NAME = "event_rpcgen.py"
21275970Scy_VERSION = "0.1"
22275970Scy
23275970Scy# Globals
24275970Scyline_count = 0
25275970Scy
26275970Scywhite = re.compile(r'\s+')
27275970Scycppcomment = re.compile(r'\/\/.*$')
28275970Scynonident = re.compile(r'[^a-zA-Z0-9_]')
29275970Scystructref = re.compile(r'^struct\[([a-zA-Z_][a-zA-Z0-9_]*)\]$')
30275970Scystructdef = re.compile(r'^struct +[a-zA-Z_][a-zA-Z0-9_]* *{$')
31275970Scy
32275970Scyheaderdirect = []
33275970Scycppdirect = []
34275970Scy
35275970ScyQUIETLY = 0
36275970Scy
37275970Scydef declare(s):
38275970Scy    if not QUIETLY:
39275970Scy        print s
40275970Scy
41275970Scydef TranslateList(mylist, mydict):
42275970Scy    return map(lambda x: x % mydict, mylist)
43275970Scy
44275970Scy# Exception class for parse errors
45275970Scyclass RpcGenError(Exception):
46275970Scy        def __init__(self, why):
47275970Scy                self.why = why
48275970Scy        def __str__(self):
49275970Scy                return str(self.why)
50275970Scy
51275970Scy# Holds everything that makes a struct
52275970Scyclass Struct:
53275970Scy    def __init__(self, name):
54275970Scy        self._name = name
55275970Scy        self._entries = []
56275970Scy        self._tags = {}
57275970Scy        declare('  Created struct: %s' % name)
58275970Scy
59275970Scy    def AddEntry(self, entry):
60275970Scy        if self._tags.has_key(entry.Tag()):
61275970Scy            raise RpcGenError(
62275970Scy                'Entry "%s" duplicates tag number %d from "%s" '
63275970Scy                'around line %d' % (entry.Name(), entry.Tag(),
64275970Scy                                    self._tags[entry.Tag()], line_count))
65275970Scy        self._entries.append(entry)
66275970Scy        self._tags[entry.Tag()] = entry.Name()
67275970Scy        declare('    Added entry: %s' % entry.Name())
68275970Scy
69275970Scy    def Name(self):
70275970Scy        return self._name
71275970Scy
72275970Scy    def EntryTagName(self, entry):
73275970Scy        """Creates the name inside an enumeration for distinguishing data
74275970Scy        types."""
75275970Scy        name = "%s_%s" % (self._name, entry.Name())
76275970Scy        return name.upper()
77275970Scy
78275970Scy    def PrintIndented(self, file, ident, code):
79275970Scy        """Takes an array, add indentation to each entry and prints it."""
80275970Scy        for entry in code:
81275970Scy            print >>file, '%s%s' % (ident, entry)
82275970Scy
83275970Scyclass StructCCode(Struct):
84275970Scy    """ Knows how to generate C code for a struct """
85275970Scy
86275970Scy    def __init__(self, name):
87275970Scy        Struct.__init__(self, name)
88275970Scy
89275970Scy    def PrintTags(self, file):
90275970Scy        """Prints the tag definitions for a structure."""
91275970Scy        print >>file, '/* Tag definition for %s */' % self._name
92275970Scy        print >>file, 'enum %s_ {' % self._name.lower()
93275970Scy        for entry in self._entries:
94275970Scy            print >>file, '  %s=%d,' % (self.EntryTagName(entry),
95275970Scy                                        entry.Tag())
96275970Scy        print >>file, '  %s_MAX_TAGS' % (self._name.upper())
97275970Scy        print >>file, '};\n'
98275970Scy
99275970Scy    def PrintForwardDeclaration(self, file):
100275970Scy        print >>file, 'struct %s;' % self._name
101275970Scy
102275970Scy    def PrintDeclaration(self, file):
103275970Scy        print >>file, '/* Structure declaration for %s */' % self._name
104275970Scy        print >>file, 'struct %s_access_ {' % self._name
105275970Scy        for entry in self._entries:
106275970Scy            dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name())
107275970Scy            dcl.extend(
108275970Scy                entry.GetDeclaration('(*%s_get)' % entry.Name()))
109275970Scy            if entry.Array():
110275970Scy                dcl.extend(
111275970Scy                    entry.AddDeclaration('(*%s_add)' % entry.Name()))
112275970Scy            self.PrintIndented(file, '  ', dcl)
113275970Scy        print >>file, '};\n'
114275970Scy
115275970Scy        print >>file, 'struct %s {' % self._name
116275970Scy        print >>file, '  struct %s_access_ *base;\n' % self._name
117275970Scy        for entry in self._entries:
118275970Scy            dcl = entry.Declaration()
119275970Scy            self.PrintIndented(file, '  ', dcl)
120275970Scy        print >>file, ''
121275970Scy        for entry in self._entries:
122275970Scy            print >>file, '  ev_uint8_t %s_set;' % entry.Name()
123275970Scy        print >>file, '};\n'
124275970Scy
125275970Scy        print >>file, \
126275970Scy"""struct %(name)s *%(name)s_new(void);
127275970Scystruct %(name)s *%(name)s_new_with_arg(void *);
128275970Scyvoid %(name)s_free(struct %(name)s *);
129275970Scyvoid %(name)s_clear(struct %(name)s *);
130275970Scyvoid %(name)s_marshal(struct evbuffer *, const struct %(name)s *);
131275970Scyint %(name)s_unmarshal(struct %(name)s *, struct evbuffer *);
132275970Scyint %(name)s_complete(struct %(name)s *);
133275970Scyvoid evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t,
134275970Scy    const struct %(name)s *);
135275970Scyint evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
136275970Scy    struct %(name)s *);""" % { 'name' : self._name }
137275970Scy
138275970Scy
139275970Scy        # Write a setting function of every variable
140275970Scy        for entry in self._entries:
141275970Scy            self.PrintIndented(file, '', entry.AssignDeclaration(
142275970Scy                entry.AssignFuncName()))
143275970Scy            self.PrintIndented(file, '', entry.GetDeclaration(
144275970Scy                entry.GetFuncName()))
145275970Scy            if entry.Array():
146275970Scy                self.PrintIndented(file, '', entry.AddDeclaration(
147275970Scy                    entry.AddFuncName()))
148275970Scy
149275970Scy        print >>file, '/* --- %s done --- */\n' % self._name
150275970Scy
151275970Scy    def PrintCode(self, file):
152275970Scy        print >>file, ('/*\n'
153275970Scy                       ' * Implementation of %s\n'
154275970Scy                       ' */\n') % self._name
155275970Scy
156275970Scy        print >>file, \
157275970Scy              'static struct %(name)s_access_ %(name)s_base__ = {' % \
158275970Scy              { 'name' : self._name }
159275970Scy        for entry in self._entries:
160275970Scy            self.PrintIndented(file, '  ', entry.CodeBase())
161275970Scy        print >>file, '};\n'
162275970Scy
163275970Scy        # Creation
164275970Scy        print >>file, (
165275970Scy            'struct %(name)s *\n'
166275970Scy            '%(name)s_new(void)\n'
167275970Scy            '{\n'
168275970Scy            '  return %(name)s_new_with_arg(NULL);\n'
169275970Scy            '}\n'
170275970Scy            '\n'
171275970Scy            'struct %(name)s *\n'
172275970Scy            '%(name)s_new_with_arg(void *unused)\n'
173275970Scy            '{\n'
174275970Scy            '  struct %(name)s *tmp;\n'
175275970Scy            '  if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n'
176275970Scy            '    event_warn("%%s: malloc", __func__);\n'
177275970Scy            '    return (NULL);\n'
178275970Scy            '  }\n'
179275970Scy            '  tmp->base = &%(name)s_base__;\n') % { 'name' : self._name }
180275970Scy
181275970Scy        for entry in self._entries:
182275970Scy            self.PrintIndented(file, '  ', entry.CodeInitialize('tmp'))
183275970Scy            print >>file, '  tmp->%s_set = 0;\n' % entry.Name()
184275970Scy
185275970Scy        print >>file, (
186275970Scy            '  return (tmp);\n'
187275970Scy            '}\n')
188275970Scy
189275970Scy        # Adding
190275970Scy        for entry in self._entries:
191275970Scy            if entry.Array():
192275970Scy                self.PrintIndented(file, '', entry.CodeAdd())
193275970Scy            print >>file, ''
194275970Scy
195275970Scy        # Assigning
196275970Scy        for entry in self._entries:
197275970Scy            self.PrintIndented(file, '', entry.CodeAssign())
198275970Scy            print >>file, ''
199275970Scy
200275970Scy        # Getting
201275970Scy        for entry in self._entries:
202275970Scy            self.PrintIndented(file, '', entry.CodeGet())
203275970Scy            print >>file, ''
204275970Scy
205275970Scy        # Clearing
206275970Scy        print >>file, ( 'void\n'
207275970Scy                        '%(name)s_clear(struct %(name)s *tmp)\n'
208275970Scy                        '{'
209275970Scy                        ) % { 'name' : self._name }
210275970Scy        for entry in self._entries:
211275970Scy            self.PrintIndented(file, '  ', entry.CodeClear('tmp'))
212275970Scy
213275970Scy        print >>file, '}\n'
214275970Scy
215275970Scy        # Freeing
216275970Scy        print >>file, ( 'void\n'
217275970Scy                        '%(name)s_free(struct %(name)s *tmp)\n'
218275970Scy                        '{'
219275970Scy                        ) % { 'name' : self._name }
220275970Scy
221275970Scy        for entry in self._entries:
222275970Scy            self.PrintIndented(file, '  ', entry.CodeFree('tmp'))
223275970Scy
224275970Scy        print >>file, ('  free(tmp);\n'
225275970Scy                       '}\n')
226275970Scy
227275970Scy        # Marshaling
228275970Scy        print >>file, ('void\n'
229275970Scy                       '%(name)s_marshal(struct evbuffer *evbuf, '
230275970Scy                       'const struct %(name)s *tmp)'
231275970Scy                       '{') % { 'name' : self._name }
232275970Scy        for entry in self._entries:
233275970Scy            indent = '  '
234275970Scy            # Optional entries do not have to be set
235275970Scy            if entry.Optional():
236275970Scy                indent += '  '
237275970Scy                print >>file, '  if (tmp->%s_set) {' % entry.Name()
238275970Scy            self.PrintIndented(
239275970Scy                file, indent,
240275970Scy                entry.CodeMarshal('evbuf', self.EntryTagName(entry),
241275970Scy                                  entry.GetVarName('tmp'),
242275970Scy                                  entry.GetVarLen('tmp')))
243275970Scy            if entry.Optional():
244275970Scy                print >>file, '  }'
245275970Scy
246275970Scy        print >>file, '}\n'
247275970Scy
248275970Scy        # Unmarshaling
249275970Scy        print >>file, ('int\n'
250275970Scy                       '%(name)s_unmarshal(struct %(name)s *tmp, '
251275970Scy                       ' struct evbuffer *evbuf)\n'
252275970Scy                       '{\n'
253275970Scy                       '  ev_uint32_t tag;\n'
254275970Scy                       '  while (evbuffer_get_length(evbuf) > 0) {\n'
255275970Scy                       '    if (evtag_peek(evbuf, &tag) == -1)\n'
256275970Scy                       '      return (-1);\n'
257275970Scy                       '    switch (tag) {\n'
258275970Scy                       ) % { 'name' : self._name }
259275970Scy        for entry in self._entries:
260275970Scy            print >>file, '      case %s:\n' % self.EntryTagName(entry)
261275970Scy            if not entry.Array():
262275970Scy                print >>file, (
263275970Scy                    '        if (tmp->%s_set)\n'
264275970Scy                    '          return (-1);'
265275970Scy                    ) % (entry.Name())
266275970Scy
267275970Scy            self.PrintIndented(
268275970Scy                file, '        ',
269275970Scy                entry.CodeUnmarshal('evbuf',
270275970Scy                                    self.EntryTagName(entry),
271275970Scy                                    entry.GetVarName('tmp'),
272275970Scy                                    entry.GetVarLen('tmp')))
273275970Scy
274275970Scy            print >>file, ( '        tmp->%s_set = 1;\n' % entry.Name() +
275275970Scy                            '        break;\n' )
276275970Scy        print >>file, ( '      default:\n'
277275970Scy                        '        return -1;\n'
278275970Scy                        '    }\n'
279275970Scy                        '  }\n' )
280275970Scy        # Check if it was decoded completely
281275970Scy        print >>file, ( '  if (%(name)s_complete(tmp) == -1)\n'
282275970Scy                        '    return (-1);'
283275970Scy                        ) % { 'name' : self._name }
284275970Scy
285275970Scy        # Successfully decoded
286275970Scy        print >>file, ( '  return (0);\n'
287275970Scy                        '}\n')
288275970Scy
289275970Scy        # Checking if a structure has all the required data
290275970Scy        print >>file, (
291275970Scy            'int\n'
292275970Scy            '%(name)s_complete(struct %(name)s *msg)\n'
293275970Scy            '{' ) % { 'name' : self._name }
294275970Scy        for entry in self._entries:
295275970Scy            if not entry.Optional():
296275970Scy                code = [
297275970Scy                    'if (!msg->%(name)s_set)',
298275970Scy                    '  return (-1);' ]
299275970Scy                code = TranslateList(code, entry.GetTranslation())
300275970Scy                self.PrintIndented(
301275970Scy                    file, '  ', code)
302275970Scy
303275970Scy            self.PrintIndented(
304275970Scy                file, '  ',
305275970Scy                entry.CodeComplete('msg', entry.GetVarName('msg')))
306275970Scy        print >>file, (
307275970Scy            '  return (0);\n'
308275970Scy            '}\n' )
309275970Scy
310275970Scy        # Complete message unmarshaling
311275970Scy        print >>file, (
312275970Scy            'int\n'
313275970Scy            'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, '
314275970Scy            'ev_uint32_t need_tag, struct %(name)s *msg)\n'
315275970Scy            '{\n'
316275970Scy            '  ev_uint32_t tag;\n'
317275970Scy            '  int res = -1;\n'
318275970Scy            '\n'
319275970Scy            '  struct evbuffer *tmp = evbuffer_new();\n'
320275970Scy            '\n'
321275970Scy            '  if (evtag_unmarshal(evbuf, &tag, tmp) == -1'
322275970Scy            ' || tag != need_tag)\n'
323275970Scy            '    goto error;\n'
324275970Scy            '\n'
325275970Scy            '  if (%(name)s_unmarshal(msg, tmp) == -1)\n'
326275970Scy            '    goto error;\n'
327275970Scy            '\n'
328275970Scy            '  res = 0;\n'
329275970Scy            '\n'
330275970Scy            ' error:\n'
331275970Scy            '  evbuffer_free(tmp);\n'
332275970Scy            '  return (res);\n'
333275970Scy            '}\n' ) % { 'name' : self._name }
334275970Scy
335275970Scy        # Complete message marshaling
336275970Scy        print >>file, (
337275970Scy            'void\n'
338275970Scy            'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, '
339275970Scy            'const struct %(name)s *msg)\n'
340275970Scy            '{\n'
341275970Scy            '  struct evbuffer *buf_ = evbuffer_new();\n'
342275970Scy            '  assert(buf_ != NULL);\n'
343275970Scy            '  %(name)s_marshal(buf_, msg);\n'
344275970Scy            '  evtag_marshal_buffer(evbuf, tag, buf_);\n '
345275970Scy            '  evbuffer_free(buf_);\n'
346275970Scy            '}\n' ) % { 'name' : self._name }
347275970Scy
348275970Scyclass Entry:
349275970Scy    def __init__(self, type, name, tag):
350275970Scy        self._type = type
351275970Scy        self._name = name
352275970Scy        self._tag = int(tag)
353275970Scy        self._ctype = type
354275970Scy        self._optional = 0
355275970Scy        self._can_be_array = 0
356275970Scy        self._array = 0
357275970Scy        self._line_count = -1
358275970Scy        self._struct = None
359275970Scy        self._refname = None
360275970Scy
361275970Scy        self._optpointer = True
362275970Scy        self._optaddarg = True
363275970Scy
364275970Scy    def GetInitializer(self):
365275970Scy        assert 0, "Entry does not provide initializer"
366275970Scy
367275970Scy    def SetStruct(self, struct):
368275970Scy        self._struct = struct
369275970Scy
370275970Scy    def LineCount(self):
371275970Scy        assert self._line_count != -1
372275970Scy        return self._line_count
373275970Scy
374275970Scy    def SetLineCount(self, number):
375275970Scy        self._line_count = number
376275970Scy
377275970Scy    def Array(self):
378275970Scy        return self._array
379275970Scy
380275970Scy    def Optional(self):
381275970Scy        return self._optional
382275970Scy
383275970Scy    def Tag(self):
384275970Scy        return self._tag
385275970Scy
386275970Scy    def Name(self):
387275970Scy        return self._name
388275970Scy
389275970Scy    def Type(self):
390275970Scy        return self._type
391275970Scy
392275970Scy    def MakeArray(self, yes=1):
393275970Scy        self._array = yes
394275970Scy
395275970Scy    def MakeOptional(self):
396275970Scy        self._optional = 1
397275970Scy
398275970Scy    def Verify(self):
399275970Scy        if self.Array() and not self._can_be_array:
400275970Scy            raise RpcGenError(
401275970Scy                'Entry "%s" cannot be created as an array '
402275970Scy                'around line %d' % (self._name, self.LineCount()))
403275970Scy        if not self._struct:
404275970Scy            raise RpcGenError(
405275970Scy                'Entry "%s" does not know which struct it belongs to '
406275970Scy                'around line %d' % (self._name, self.LineCount()))
407275970Scy        if self._optional and self._array:
408275970Scy            raise RpcGenError(
409275970Scy                'Entry "%s" has illegal combination of optional and array '
410275970Scy                'around line %d' % (self._name, self.LineCount()))
411275970Scy
412275970Scy    def GetTranslation(self, extradict = {}):
413275970Scy        mapping = {
414275970Scy            "parent_name" : self._struct.Name(),
415275970Scy            "name" : self._name,
416275970Scy            "ctype" : self._ctype,
417275970Scy            "refname" : self._refname,
418275970Scy            "optpointer" : self._optpointer and "*" or "",
419275970Scy            "optreference" : self._optpointer and "&" or "",
420275970Scy            "optaddarg" :
421275970Scy            self._optaddarg and ", const %s value" % self._ctype or ""
422275970Scy            }
423275970Scy        for (k, v) in extradict.items():
424275970Scy            mapping[k] = v
425275970Scy
426275970Scy        return mapping
427275970Scy
428275970Scy    def GetVarName(self, var):
429275970Scy        return '%(var)s->%(name)s_data' % self.GetTranslation({ 'var' : var })
430275970Scy
431275970Scy    def GetVarLen(self, var):
432275970Scy        return 'sizeof(%s)' % self._ctype
433275970Scy
434275970Scy    def GetFuncName(self):
435275970Scy        return '%s_%s_get' % (self._struct.Name(), self._name)
436275970Scy
437275970Scy    def GetDeclaration(self, funcname):
438275970Scy        code = [ 'int %s(struct %s *, %s *);' % (
439275970Scy            funcname, self._struct.Name(), self._ctype ) ]
440275970Scy        return code
441275970Scy
442275970Scy    def CodeGet(self):
443275970Scy        code = (
444275970Scy            'int',
445275970Scy            '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, '
446275970Scy            '%(ctype)s *value)',
447275970Scy            '{',
448275970Scy            '  if (msg->%(name)s_set != 1)',
449275970Scy            '    return (-1);',
450275970Scy            '  *value = msg->%(name)s_data;',
451275970Scy            '  return (0);',
452275970Scy            '}' )
453275970Scy        code = '\n'.join(code)
454275970Scy        code = code % self.GetTranslation()
455275970Scy        return code.split('\n')
456275970Scy
457275970Scy    def AssignFuncName(self):
458275970Scy        return '%s_%s_assign' % (self._struct.Name(), self._name)
459275970Scy
460275970Scy    def AddFuncName(self):
461275970Scy        return '%s_%s_add' % (self._struct.Name(), self._name)
462275970Scy
463275970Scy    def AssignDeclaration(self, funcname):
464275970Scy        code = [ 'int %s(struct %s *, const %s);' % (
465275970Scy            funcname, self._struct.Name(), self._ctype ) ]
466275970Scy        return code
467275970Scy
468275970Scy    def CodeAssign(self):
469275970Scy        code = [ 'int',
470275970Scy                 '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,'
471275970Scy                 ' const %(ctype)s value)',
472275970Scy                 '{',
473275970Scy                 '  msg->%(name)s_set = 1;',
474275970Scy                 '  msg->%(name)s_data = value;',
475275970Scy                 '  return (0);',
476275970Scy                 '}' ]
477275970Scy        code = '\n'.join(code)
478275970Scy        code = code % self.GetTranslation()
479275970Scy        return code.split('\n')
480275970Scy
481275970Scy    def CodeClear(self, structname):
482275970Scy        code = [ '%s->%s_set = 0;' % (structname, self.Name()) ]
483275970Scy
484275970Scy        return code
485275970Scy
486275970Scy    def CodeComplete(self, structname, var_name):
487275970Scy        return []
488275970Scy
489275970Scy    def CodeFree(self, name):
490275970Scy        return []
491275970Scy
492275970Scy    def CodeBase(self):
493275970Scy        code = [
494275970Scy            '%(parent_name)s_%(name)s_assign,',
495275970Scy            '%(parent_name)s_%(name)s_get,'
496275970Scy            ]
497275970Scy        if self.Array():
498275970Scy            code.append('%(parent_name)s_%(name)s_add,')
499275970Scy
500275970Scy        code = '\n'.join(code)
501275970Scy        code = code % self.GetTranslation()
502275970Scy        return code.split('\n')
503275970Scy
504275970Scyclass EntryBytes(Entry):
505275970Scy    def __init__(self, type, name, tag, length):
506275970Scy        # Init base class
507275970Scy        Entry.__init__(self, type, name, tag)
508275970Scy
509275970Scy        self._length = length
510275970Scy        self._ctype = 'ev_uint8_t'
511275970Scy
512275970Scy    def GetInitializer(self):
513275970Scy        return "NULL"
514275970Scy
515275970Scy    def GetVarLen(self, var):
516275970Scy        return '(%s)' % self._length
517275970Scy
518275970Scy    def CodeArrayAdd(self, varname, value):
519275970Scy        # XXX: copy here
520275970Scy        return [ '%(varname)s = NULL;' % { 'varname' : varname } ]
521275970Scy
522275970Scy    def GetDeclaration(self, funcname):
523275970Scy        code = [ 'int %s(struct %s *, %s **);' % (
524275970Scy            funcname, self._struct.Name(), self._ctype ) ]
525275970Scy        return code
526275970Scy
527275970Scy    def AssignDeclaration(self, funcname):
528275970Scy        code = [ 'int %s(struct %s *, const %s *);' % (
529275970Scy            funcname, self._struct.Name(), self._ctype ) ]
530275970Scy        return code
531275970Scy
532275970Scy    def Declaration(self):
533275970Scy        dcl  = ['ev_uint8_t %s_data[%s];' % (self._name, self._length)]
534275970Scy
535275970Scy        return dcl
536275970Scy
537275970Scy    def CodeGet(self):
538275970Scy        name = self._name
539275970Scy        code = [ 'int',
540275970Scy                 '%s_%s_get(struct %s *msg, %s **value)' % (
541275970Scy            self._struct.Name(), name,
542275970Scy            self._struct.Name(), self._ctype),
543275970Scy                 '{',
544275970Scy                 '  if (msg->%s_set != 1)' % name,
545275970Scy                 '    return (-1);',
546275970Scy                 '  *value = msg->%s_data;' % name,
547275970Scy                 '  return (0);',
548275970Scy                 '}' ]
549275970Scy        return code
550275970Scy
551275970Scy    def CodeAssign(self):
552275970Scy        name = self._name
553275970Scy        code = [ 'int',
554275970Scy                 '%s_%s_assign(struct %s *msg, const %s *value)' % (
555275970Scy            self._struct.Name(), name,
556275970Scy            self._struct.Name(), self._ctype),
557275970Scy                 '{',
558275970Scy                 '  msg->%s_set = 1;' % name,
559275970Scy                 '  memcpy(msg->%s_data, value, %s);' % (
560275970Scy            name, self._length),
561275970Scy                 '  return (0);',
562275970Scy                 '}' ]
563275970Scy        return code
564275970Scy
565275970Scy    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
566275970Scy        code = [  'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, '
567275970Scy                  '%(var)s, %(varlen)s) == -1) {',
568275970Scy                  '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
569275970Scy                  '  return (-1);',
570275970Scy                  '}'
571275970Scy                  ]
572275970Scy        return TranslateList(code,
573275970Scy                             self.GetTranslation({
574275970Scy            'var' : var_name,
575275970Scy            'varlen' : var_len,
576275970Scy            'buf' : buf,
577275970Scy            'tag' : tag_name }))
578275970Scy
579275970Scy    def CodeMarshal(self, buf, tag_name, var_name, var_len):
580275970Scy        code = ['evtag_marshal(%s, %s, %s, %s);' % (
581275970Scy            buf, tag_name, var_name, var_len)]
582275970Scy        return code
583275970Scy
584275970Scy    def CodeClear(self, structname):
585275970Scy        code = [ '%s->%s_set = 0;' % (structname, self.Name()),
586275970Scy                 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
587275970Scy            structname, self._name, structname, self._name)]
588275970Scy
589275970Scy        return code
590275970Scy
591275970Scy    def CodeInitialize(self, name):
592275970Scy        code  = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
593275970Scy            name, self._name, name, self._name)]
594275970Scy        return code
595275970Scy
596275970Scy    def Verify(self):
597275970Scy        if not self._length:
598275970Scy            raise RpcGenError(
599275970Scy                'Entry "%s" needs a length '
600275970Scy                'around line %d' % (self._name, self.LineCount()))
601275970Scy
602275970Scy        Entry.Verify(self)
603275970Scy
604275970Scyclass EntryInt(Entry):
605275970Scy    def __init__(self, type, name, tag, bits=32):
606275970Scy        # Init base class
607275970Scy        Entry.__init__(self, type, name, tag)
608275970Scy
609275970Scy        self._can_be_array = 1
610275970Scy        if bits == 32:
611275970Scy            self._ctype = 'ev_uint32_t'
612275970Scy            self._marshal_type = 'int'
613275970Scy        if bits == 64:
614275970Scy            self._ctype = 'ev_uint64_t'
615275970Scy            self._marshal_type = 'int64'
616275970Scy
617275970Scy    def GetInitializer(self):
618275970Scy        return "0"
619275970Scy
620275970Scy    def CodeArrayFree(self, var):
621275970Scy        return []
622275970Scy
623275970Scy    def CodeArrayAssign(self, varname, srcvar):
624275970Scy        return [ '%(varname)s = %(srcvar)s;' % { 'varname' : varname,
625275970Scy                                                'srcvar' : srcvar } ]
626275970Scy
627275970Scy    def CodeArrayAdd(self, varname, value):
628275970Scy        """Returns a new entry of this type."""
629275970Scy        return [ '%(varname)s = %(value)s;' % { 'varname' : varname,
630275970Scy                                              'value' : value } ]
631275970Scy
632275970Scy    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
633275970Scy        code = [
634275970Scy            'if (evtag_unmarshal_%(ma)s(%(buf)s, %(tag)s, &%(var)s) == -1) {',
635275970Scy            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
636275970Scy            '  return (-1);',
637275970Scy            '}' ]
638275970Scy        code = '\n'.join(code) % self.GetTranslation({
639275970Scy            'ma'  : self._marshal_type,
640275970Scy            'buf' : buf,
641275970Scy            'tag' : tag_name,
642275970Scy            'var' : var_name })
643275970Scy        return code.split('\n')
644275970Scy
645275970Scy    def CodeMarshal(self, buf, tag_name, var_name, var_len):
646275970Scy        code = [
647275970Scy            'evtag_marshal_%s(%s, %s, %s);' % (
648275970Scy            self._marshal_type, buf, tag_name, var_name)]
649275970Scy        return code
650275970Scy
651275970Scy    def Declaration(self):
652275970Scy        dcl  = ['%s %s_data;' % (self._ctype, self._name)]
653275970Scy
654275970Scy        return dcl
655275970Scy
656275970Scy    def CodeInitialize(self, name):
657275970Scy        code = ['%s->%s_data = 0;' % (name, self._name)]
658275970Scy        return code
659275970Scy
660275970Scyclass EntryString(Entry):
661275970Scy    def __init__(self, type, name, tag):
662275970Scy        # Init base class
663275970Scy        Entry.__init__(self, type, name, tag)
664275970Scy
665275970Scy        self._can_be_array = 1
666275970Scy        self._ctype = 'char *'
667275970Scy
668275970Scy    def GetInitializer(self):
669275970Scy        return "NULL"
670275970Scy
671275970Scy    def CodeArrayFree(self, varname):
672275970Scy        code = [
673275970Scy            'if (%(var)s != NULL) free(%(var)s);' ]
674275970Scy
675275970Scy        return TranslateList(code, { 'var' : varname })
676275970Scy
677275970Scy    def CodeArrayAssign(self, varname, srcvar):
678275970Scy        code = [
679275970Scy            'if (%(var)s != NULL)',
680275970Scy            '  free(%(var)s);',
681275970Scy            '%(var)s = strdup(%(srcvar)s);',
682275970Scy            'if (%(var)s == NULL) {',
683275970Scy            '  event_warnx("%%s: strdup", __func__);',
684275970Scy            '  return (-1);',
685275970Scy            '}' ]
686275970Scy
687275970Scy        return TranslateList(code, { 'var' : varname,
688275970Scy                                     'srcvar' : srcvar })
689275970Scy
690275970Scy    def CodeArrayAdd(self, varname, value):
691275970Scy        code = [
692275970Scy            'if (%(value)s != NULL) {',
693275970Scy            '  %(var)s = strdup(%(value)s);',
694275970Scy            '  if (%(var)s == NULL) {',
695275970Scy            '    goto error;',
696275970Scy            '  }',
697275970Scy            '} else {',
698275970Scy            '  %(var)s = NULL;',
699275970Scy            '}' ]
700275970Scy
701275970Scy        return TranslateList(code, { 'var' : varname,
702275970Scy                                     'value' : value })
703275970Scy
704275970Scy    def GetVarLen(self, var):
705275970Scy        return 'strlen(%s)' % self.GetVarName(var)
706275970Scy
707275970Scy    def CodeMakeInitalize(self, varname):
708275970Scy        return '%(varname)s = NULL;' % { 'varname' : varname }
709275970Scy
710275970Scy    def CodeAssign(self):
711275970Scy        name = self._name
712275970Scy        code = """int
713275970Scy%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
714275970Scy    const %(ctype)s value)
715275970Scy{
716275970Scy  if (msg->%(name)s_data != NULL)
717275970Scy    free(msg->%(name)s_data);
718275970Scy  if ((msg->%(name)s_data = strdup(value)) == NULL)
719275970Scy    return (-1);
720275970Scy  msg->%(name)s_set = 1;
721275970Scy  return (0);
722275970Scy}""" % self.GetTranslation()
723275970Scy
724275970Scy        return code.split('\n')
725275970Scy
726275970Scy    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
727275970Scy        code = ['if (evtag_unmarshal_string(%(buf)s, %(tag)s, &%(var)s) == -1) {',
728275970Scy                '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
729275970Scy                '  return (-1);',
730275970Scy                '}'
731275970Scy                ]
732275970Scy        code = '\n'.join(code) % self.GetTranslation({
733275970Scy            'buf' : buf,
734275970Scy            'tag' : tag_name,
735275970Scy            'var' : var_name })
736275970Scy        return code.split('\n')
737275970Scy
738275970Scy    def CodeMarshal(self, buf, tag_name, var_name, var_len):
739275970Scy        code = ['evtag_marshal_string(%s, %s, %s);' % (
740275970Scy            buf, tag_name, var_name)]
741275970Scy        return code
742275970Scy
743275970Scy    def CodeClear(self, structname):
744275970Scy        code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
745275970Scy                 '  free(%s->%s_data);' % (structname, self.Name()),
746275970Scy                 '  %s->%s_data = NULL;' % (structname, self.Name()),
747275970Scy                 '  %s->%s_set = 0;' % (structname, self.Name()),
748275970Scy                 '}'
749275970Scy                 ]
750275970Scy
751275970Scy        return code
752275970Scy
753275970Scy    def CodeInitialize(self, name):
754275970Scy        code  = ['%s->%s_data = NULL;' % (name, self._name)]
755275970Scy        return code
756275970Scy
757275970Scy    def CodeFree(self, name):
758275970Scy        code  = ['if (%s->%s_data != NULL)' % (name, self._name),
759275970Scy                 '    free (%s->%s_data);' % (name, self._name)]
760275970Scy
761275970Scy        return code
762275970Scy
763275970Scy    def Declaration(self):
764275970Scy        dcl  = ['char *%s_data;' % self._name]
765275970Scy
766275970Scy        return dcl
767275970Scy
768275970Scyclass EntryStruct(Entry):
769275970Scy    def __init__(self, type, name, tag, refname):
770275970Scy        # Init base class
771275970Scy        Entry.__init__(self, type, name, tag)
772275970Scy
773275970Scy        self._optpointer = False
774275970Scy        self._can_be_array = 1
775275970Scy        self._refname = refname
776275970Scy        self._ctype = 'struct %s*' % refname
777275970Scy        self._optaddarg = False
778275970Scy
779275970Scy    def GetInitializer(self):
780275970Scy        return "NULL"
781275970Scy
782275970Scy    def GetVarLen(self, var):
783275970Scy        return '-1'
784275970Scy
785275970Scy    def CodeArrayAdd(self, varname, value):
786275970Scy        code = [
787275970Scy            '%(varname)s = %(refname)s_new();',
788275970Scy            'if (%(varname)s == NULL)',
789275970Scy            '  goto error;' ]
790275970Scy
791275970Scy        return TranslateList(code, self.GetTranslation({ 'varname' : varname }))
792275970Scy
793275970Scy    def CodeArrayFree(self, var):
794275970Scy        code = [ '%(refname)s_free(%(var)s);' % self.GetTranslation(
795275970Scy            { 'var' : var }) ]
796275970Scy        return code
797275970Scy
798275970Scy    def CodeArrayAssign(self, var, srcvar):
799275970Scy        code = [
800275970Scy            'int had_error = 0;',
801275970Scy            'struct evbuffer *tmp = NULL;',
802275970Scy            '%(refname)s_clear(%(var)s);',
803275970Scy            'if ((tmp = evbuffer_new()) == NULL) {',
804275970Scy            '  event_warn("%%s: evbuffer_new()", __func__);',
805275970Scy            '  had_error = 1;',
806275970Scy            '  goto done;',
807275970Scy            '}',
808275970Scy            '%(refname)s_marshal(tmp, %(srcvar)s);',
809275970Scy            'if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {',
810275970Scy            '  event_warnx("%%s: %(refname)s_unmarshal", __func__);',
811275970Scy            '  had_error = 1;',
812275970Scy            '  goto done;',
813275970Scy            '}',
814275970Scy            'done:'
815275970Scy            'if (tmp != NULL)',
816275970Scy            '  evbuffer_free(tmp);',
817275970Scy            'if (had_error) {',
818275970Scy            '  %(refname)s_clear(%(var)s);',
819275970Scy            '  return (-1);',
820275970Scy            '}' ]
821275970Scy
822275970Scy        return TranslateList(code, self.GetTranslation({
823275970Scy            'var' : var,
824275970Scy            'srcvar' : srcvar}))
825275970Scy
826275970Scy    def CodeGet(self):
827275970Scy        name = self._name
828275970Scy        code = [ 'int',
829275970Scy                 '%s_%s_get(struct %s *msg, %s *value)' % (
830275970Scy            self._struct.Name(), name,
831275970Scy            self._struct.Name(), self._ctype),
832275970Scy                 '{',
833275970Scy                 '  if (msg->%s_set != 1) {' % name,
834275970Scy                 '    msg->%s_data = %s_new();' % (name, self._refname),
835275970Scy                 '    if (msg->%s_data == NULL)' % name,
836275970Scy                 '      return (-1);',
837275970Scy                 '    msg->%s_set = 1;' % name,
838275970Scy                 '  }',
839275970Scy                 '  *value = msg->%s_data;' % name,
840275970Scy                 '  return (0);',
841275970Scy                 '}' ]
842275970Scy        return code
843275970Scy
844275970Scy    def CodeAssign(self):
845275970Scy        name = self._name
846275970Scy        code = """int
847275970Scy%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
848275970Scy    const %(ctype)s value)
849275970Scy{
850275970Scy   struct evbuffer *tmp = NULL;
851275970Scy   if (msg->%(name)s_set) {
852275970Scy     %(refname)s_clear(msg->%(name)s_data);
853275970Scy     msg->%(name)s_set = 0;
854275970Scy   } else {
855275970Scy     msg->%(name)s_data = %(refname)s_new();
856275970Scy     if (msg->%(name)s_data == NULL) {
857275970Scy       event_warn("%%s: %(refname)s_new()", __func__);
858275970Scy       goto error;
859275970Scy     }
860275970Scy   }
861275970Scy   if ((tmp = evbuffer_new()) == NULL) {
862275970Scy     event_warn("%%s: evbuffer_new()", __func__);
863275970Scy     goto error;
864275970Scy   }
865275970Scy   %(refname)s_marshal(tmp, value);
866275970Scy   if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) {
867275970Scy     event_warnx("%%s: %(refname)s_unmarshal", __func__);
868275970Scy     goto error;
869275970Scy   }
870275970Scy   msg->%(name)s_set = 1;
871275970Scy   evbuffer_free(tmp);
872275970Scy   return (0);
873275970Scy error:
874275970Scy   if (tmp != NULL)
875275970Scy     evbuffer_free(tmp);
876275970Scy   if (msg->%(name)s_data != NULL) {
877275970Scy     %(refname)s_free(msg->%(name)s_data);
878275970Scy     msg->%(name)s_data = NULL;
879275970Scy   }
880275970Scy   return (-1);
881275970Scy}""" % self.GetTranslation()
882275970Scy        return code.split('\n')
883275970Scy
884275970Scy    def CodeComplete(self, structname, var_name):
885275970Scy        code = [ 'if (%(structname)s->%(name)s_set && '
886275970Scy                 '%(refname)s_complete(%(var)s) == -1)',
887275970Scy                 '  return (-1);' ]
888275970Scy
889275970Scy        return TranslateList(code, self.GetTranslation({
890275970Scy            'structname' : structname,
891275970Scy            'var' : var_name }))
892275970Scy
893275970Scy    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
894275970Scy        code = ['%(var)s = %(refname)s_new();',
895275970Scy                'if (%(var)s == NULL)',
896275970Scy                '  return (-1);',
897275970Scy                'if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag)s, '
898275970Scy                '%(var)s) == -1) {',
899275970Scy                  '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
900275970Scy                '  return (-1);',
901275970Scy                '}'
902275970Scy                ]
903275970Scy        code = '\n'.join(code) % self.GetTranslation({
904275970Scy            'buf' : buf,
905275970Scy            'tag' : tag_name,
906275970Scy            'var' : var_name })
907275970Scy        return code.split('\n')
908275970Scy
909275970Scy    def CodeMarshal(self, buf, tag_name, var_name, var_len):
910275970Scy        code = ['evtag_marshal_%s(%s, %s, %s);' % (
911275970Scy            self._refname, buf, tag_name, var_name)]
912275970Scy        return code
913275970Scy
914275970Scy    def CodeClear(self, structname):
915275970Scy        code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
916275970Scy                 '  %s_free(%s->%s_data);' % (
917275970Scy            self._refname, structname, self.Name()),
918275970Scy                 '  %s->%s_data = NULL;' % (structname, self.Name()),
919275970Scy                 '  %s->%s_set = 0;' % (structname, self.Name()),
920275970Scy                 '}'
921275970Scy                 ]
922275970Scy
923275970Scy        return code
924275970Scy
925275970Scy    def CodeInitialize(self, name):
926275970Scy        code  = ['%s->%s_data = NULL;' % (name, self._name)]
927275970Scy        return code
928275970Scy
929275970Scy    def CodeFree(self, name):
930275970Scy        code  = ['if (%s->%s_data != NULL)' % (name, self._name),
931275970Scy                 '    %s_free(%s->%s_data);' % (
932275970Scy            self._refname, name, self._name)]
933275970Scy
934275970Scy        return code
935275970Scy
936275970Scy    def Declaration(self):
937275970Scy        dcl  = ['%s %s_data;' % (self._ctype, self._name)]
938275970Scy
939275970Scy        return dcl
940275970Scy
941275970Scyclass EntryVarBytes(Entry):
942275970Scy    def __init__(self, type, name, tag):
943275970Scy        # Init base class
944275970Scy        Entry.__init__(self, type, name, tag)
945275970Scy
946275970Scy        self._ctype = 'ev_uint8_t *'
947275970Scy
948275970Scy    def GetInitializer(self):
949275970Scy        return "NULL"
950275970Scy
951275970Scy    def GetVarLen(self, var):
952275970Scy        return '%(var)s->%(name)s_length' % self.GetTranslation({ 'var' : var })
953275970Scy
954275970Scy    def CodeArrayAdd(self, varname, value):
955275970Scy        # xxx: copy
956275970Scy        return [ '%(varname)s = NULL;' % { 'varname' : varname } ]
957275970Scy
958275970Scy    def GetDeclaration(self, funcname):
959275970Scy        code = [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % (
960275970Scy            funcname, self._struct.Name(), self._ctype ) ]
961275970Scy        return code
962275970Scy
963275970Scy    def AssignDeclaration(self, funcname):
964275970Scy        code = [ 'int %s(struct %s *, const %s, ev_uint32_t);' % (
965275970Scy            funcname, self._struct.Name(), self._ctype ) ]
966275970Scy        return code
967275970Scy
968275970Scy    def CodeAssign(self):
969275970Scy        name = self._name
970275970Scy        code = [ 'int',
971275970Scy                 '%s_%s_assign(struct %s *msg, '
972275970Scy                 'const %s value, ev_uint32_t len)' % (
973275970Scy            self._struct.Name(), name,
974275970Scy            self._struct.Name(), self._ctype),
975275970Scy                 '{',
976275970Scy                 '  if (msg->%s_data != NULL)' % name,
977275970Scy                 '    free (msg->%s_data);' % name,
978275970Scy                 '  msg->%s_data = malloc(len);' % name,
979275970Scy                 '  if (msg->%s_data == NULL)' % name,
980275970Scy                 '    return (-1);',
981275970Scy                 '  msg->%s_set = 1;' % name,
982275970Scy                 '  msg->%s_length = len;' % name,
983275970Scy                 '  memcpy(msg->%s_data, value, len);' % name,
984275970Scy                 '  return (0);',
985275970Scy                 '}' ]
986275970Scy        return code
987275970Scy
988275970Scy    def CodeGet(self):
989275970Scy        name = self._name
990275970Scy        code = [ 'int',
991275970Scy                 '%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)' % (
992275970Scy            self._struct.Name(), name,
993275970Scy            self._struct.Name(), self._ctype),
994275970Scy                 '{',
995275970Scy                 '  if (msg->%s_set != 1)' % name,
996275970Scy                 '    return (-1);',
997275970Scy                 '  *value = msg->%s_data;' % name,
998275970Scy                 '  *plen = msg->%s_length;' % name,
999275970Scy                 '  return (0);',
1000275970Scy                 '}' ]
1001275970Scy        return code
1002275970Scy
1003275970Scy    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
1004275970Scy        code = ['if (evtag_payload_length(%(buf)s, &%(varlen)s) == -1)',
1005275970Scy                '  return (-1);',
1006275970Scy                # We do not want DoS opportunities
1007275970Scy                'if (%(varlen)s > evbuffer_get_length(%(buf)s))',
1008275970Scy                '  return (-1);',
1009275970Scy                'if ((%(var)s = malloc(%(varlen)s)) == NULL)',
1010275970Scy                '  return (-1);',
1011275970Scy                'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, %(var)s, '
1012275970Scy                '%(varlen)s) == -1) {',
1013275970Scy                '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
1014275970Scy                '  return (-1);',
1015275970Scy                '}'
1016275970Scy                ]
1017275970Scy        code = '\n'.join(code) % self.GetTranslation({
1018275970Scy            'buf' : buf,
1019275970Scy            'tag' : tag_name,
1020275970Scy            'var' : var_name,
1021275970Scy            'varlen' : var_len })
1022275970Scy        return code.split('\n')
1023275970Scy
1024275970Scy    def CodeMarshal(self, buf, tag_name, var_name, var_len):
1025275970Scy        code = ['evtag_marshal(%s, %s, %s, %s);' % (
1026275970Scy            buf, tag_name, var_name, var_len)]
1027275970Scy        return code
1028275970Scy
1029275970Scy    def CodeClear(self, structname):
1030275970Scy        code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
1031275970Scy                 '  free (%s->%s_data);' % (structname, self.Name()),
1032275970Scy                 '  %s->%s_data = NULL;' % (structname, self.Name()),
1033275970Scy                 '  %s->%s_length = 0;' % (structname, self.Name()),
1034275970Scy                 '  %s->%s_set = 0;' % (structname, self.Name()),
1035275970Scy                 '}'
1036275970Scy                 ]
1037275970Scy
1038275970Scy        return code
1039275970Scy
1040275970Scy    def CodeInitialize(self, name):
1041275970Scy        code  = ['%s->%s_data = NULL;' % (name, self._name),
1042275970Scy                 '%s->%s_length = 0;' % (name, self._name) ]
1043275970Scy        return code
1044275970Scy
1045275970Scy    def CodeFree(self, name):
1046275970Scy        code  = ['if (%s->%s_data != NULL)' % (name, self._name),
1047275970Scy                 '    free(%s->%s_data);' % (name, self._name)]
1048275970Scy
1049275970Scy        return code
1050275970Scy
1051275970Scy    def Declaration(self):
1052275970Scy        dcl  = ['ev_uint8_t *%s_data;' % self._name,
1053275970Scy                'ev_uint32_t %s_length;' % self._name]
1054275970Scy
1055275970Scy        return dcl
1056275970Scy
1057275970Scyclass EntryArray(Entry):
1058275970Scy    def __init__(self, entry):
1059275970Scy        # Init base class
1060275970Scy        Entry.__init__(self, entry._type, entry._name, entry._tag)
1061275970Scy
1062275970Scy        self._entry = entry
1063275970Scy        self._refname = entry._refname
1064275970Scy        self._ctype = self._entry._ctype
1065275970Scy        self._optional = True
1066275970Scy        self._optpointer = self._entry._optpointer
1067275970Scy        self._optaddarg = self._entry._optaddarg
1068275970Scy
1069275970Scy        # provide a new function for accessing the variable name
1070275970Scy        def GetVarName(var_name):
1071275970Scy            return '%(var)s->%(name)s_data[%(index)s]' % \
1072275970Scy                   self._entry.GetTranslation({'var' : var_name,
1073275970Scy                                               'index' : self._index})
1074275970Scy        self._entry.GetVarName = GetVarName
1075275970Scy
1076275970Scy    def GetInitializer(self):
1077275970Scy        return "NULL"
1078275970Scy
1079275970Scy    def GetVarName(self, var_name):
1080275970Scy        return var_name
1081275970Scy
1082275970Scy    def GetVarLen(self, var_name):
1083275970Scy        return '-1'
1084275970Scy
1085275970Scy    def GetDeclaration(self, funcname):
1086275970Scy        """Allows direct access to elements of the array."""
1087275970Scy        code = [
1088275970Scy            'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' %
1089275970Scy            self.GetTranslation({ 'funcname' : funcname }) ]
1090275970Scy        return code
1091275970Scy
1092275970Scy    def AssignDeclaration(self, funcname):
1093275970Scy        code = [ 'int %s(struct %s *, int, const %s);' % (
1094275970Scy            funcname, self._struct.Name(), self._ctype ) ]
1095275970Scy        return code
1096275970Scy
1097275970Scy    def AddDeclaration(self, funcname):
1098275970Scy        code = [
1099275970Scy            '%(ctype)s %(optpointer)s '
1100275970Scy            '%(funcname)s(struct %(parent_name)s *msg%(optaddarg)s);' % \
1101275970Scy            self.GetTranslation({ 'funcname' : funcname }) ]
1102275970Scy        return code
1103275970Scy
1104275970Scy    def CodeGet(self):
1105275970Scy        code = """int
1106275970Scy%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset,
1107275970Scy    %(ctype)s *value)
1108275970Scy{
1109275970Scy  if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length)
1110275970Scy    return (-1);
1111275970Scy  *value = msg->%(name)s_data[offset];
1112275970Scy  return (0);
1113275970Scy}""" % self.GetTranslation()
1114275970Scy
1115275970Scy        return code.split('\n')
1116275970Scy
1117275970Scy    def CodeAssign(self):
1118275970Scy        code = [
1119275970Scy            'int',
1120275970Scy            '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,',
1121275970Scy            '    const %(ctype)s value)',
1122275970Scy            '{',
1123275970Scy            '  if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)',
1124275970Scy            '    return (-1);\n',
1125275970Scy            '  {' ]
1126275970Scy        code = TranslateList(code, self.GetTranslation())
1127275970Scy
1128275970Scy        codearrayassign = self._entry.CodeArrayAssign(
1129275970Scy            'msg->%(name)s_data[off]' % self.GetTranslation(), 'value')
1130275970Scy        code += map(lambda x: '    ' + x, codearrayassign)
1131275970Scy
1132275970Scy        code += TranslateList([
1133275970Scy            '  }',
1134275970Scy            '  return (0);',
1135275970Scy            '}' ], self.GetTranslation())
1136275970Scy
1137275970Scy        return code
1138275970Scy
1139275970Scy    def CodeAdd(self):
1140275970Scy        codearrayadd = self._entry.CodeArrayAdd(
1141275970Scy            'msg->%(name)s_data[msg->%(name)s_length - 1]' % self.GetTranslation(),
1142275970Scy            'value')
1143275970Scy        code = [
1144275970Scy            'static int',
1145275970Scy            '%(parent_name)s_%(name)s_expand_to_hold_more('
1146275970Scy            'struct %(parent_name)s *msg)',
1147275970Scy            '{',
1148275970Scy            '  int tobe_allocated = msg->%(name)s_num_allocated;',
1149275970Scy            '  %(ctype)s* new_data = NULL;',
1150275970Scy            '  tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;',
1151275970Scy            '  new_data = (%(ctype)s*) realloc(msg->%(name)s_data,',
1152275970Scy            '      tobe_allocated * sizeof(%(ctype)s));',
1153275970Scy            '  if (new_data == NULL)',
1154275970Scy            '    return -1;',
1155275970Scy            '  msg->%(name)s_data = new_data;',
1156275970Scy            '  msg->%(name)s_num_allocated = tobe_allocated;',
1157275970Scy            '  return 0;'
1158275970Scy            '}',
1159275970Scy            '',
1160275970Scy            '%(ctype)s %(optpointer)s',
1161275970Scy            '%(parent_name)s_%(name)s_add('
1162275970Scy            'struct %(parent_name)s *msg%(optaddarg)s)',
1163275970Scy            '{',
1164275970Scy            '  if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {',
1165275970Scy            '    if (%(parent_name)s_%(name)s_expand_to_hold_more(msg)<0)',
1166275970Scy            '      goto error;',
1167275970Scy            '  }' ]
1168275970Scy
1169275970Scy        code = TranslateList(code, self.GetTranslation())
1170275970Scy
1171275970Scy        code += map(lambda x: '  ' + x, codearrayadd)
1172275970Scy
1173275970Scy        code += TranslateList([
1174275970Scy            '  msg->%(name)s_set = 1;',
1175275970Scy            '  return %(optreference)s(msg->%(name)s_data['
1176275970Scy            'msg->%(name)s_length - 1]);',
1177275970Scy            'error:',
1178275970Scy            '  --msg->%(name)s_length;',
1179275970Scy            '  return (NULL);',
1180275970Scy            '}' ], self.GetTranslation())
1181275970Scy
1182275970Scy        return code
1183275970Scy
1184275970Scy    def CodeComplete(self, structname, var_name):
1185275970Scy        self._index = 'i'
1186275970Scy        tmp = self._entry.CodeComplete(structname, self._entry.GetVarName(var_name))
1187275970Scy        # skip the whole loop if there is nothing to check
1188275970Scy        if not tmp:
1189275970Scy            return []
1190275970Scy
1191275970Scy        translate = self.GetTranslation({ 'structname' : structname })
1192275970Scy        code = [
1193275970Scy            '{',
1194275970Scy            '  int i;',
1195275970Scy            '  for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ]
1196275970Scy
1197275970Scy        code = TranslateList(code, translate)
1198275970Scy
1199275970Scy        code += map(lambda x: '    ' + x, tmp)
1200275970Scy
1201275970Scy        code += [
1202275970Scy            '  }',
1203275970Scy            '}' ]
1204275970Scy
1205275970Scy        return code
1206275970Scy
1207275970Scy    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
1208275970Scy        translate = self.GetTranslation({ 'var' : var_name,
1209275970Scy                                          'buf' : buf,
1210275970Scy                                          'tag' : tag_name,
1211275970Scy                                          'init' : self._entry.GetInitializer()})
1212275970Scy        code = [
1213275970Scy            'if (%(var)s->%(name)s_length >= %(var)s->%(name)s_num_allocated &&',
1214275970Scy            '    %(parent_name)s_%(name)s_expand_to_hold_more(%(var)s) < 0) {',
1215275970Scy            '  puts("HEY NOW");',
1216275970Scy            '  return (-1);',
1217275970Scy            '}']
1218275970Scy
1219275970Scy        # the unmarshal code directly returns
1220275970Scy        code = TranslateList(code, translate)
1221275970Scy
1222275970Scy        self._index = '%(var)s->%(name)s_length' % translate
1223275970Scy        code += self._entry.CodeUnmarshal(buf, tag_name,
1224275970Scy                                        self._entry.GetVarName(var_name),
1225275970Scy                                        self._entry.GetVarLen(var_name))
1226275970Scy
1227275970Scy        code += [ '++%(var)s->%(name)s_length;' % translate ]
1228275970Scy
1229275970Scy        return code
1230275970Scy
1231275970Scy    def CodeMarshal(self, buf, tag_name, var_name, var_len):
1232275970Scy        code = ['{',
1233275970Scy                '  int i;',
1234275970Scy                '  for (i = 0; i < %(var)s->%(name)s_length; ++i) {' ]
1235275970Scy
1236275970Scy        self._index = 'i'
1237275970Scy        code += self._entry.CodeMarshal(buf, tag_name,
1238275970Scy                                        self._entry.GetVarName(var_name),
1239275970Scy                                        self._entry.GetVarLen(var_name))
1240275970Scy        code += ['  }',
1241275970Scy                 '}'
1242275970Scy                 ]
1243275970Scy
1244275970Scy        code = "\n".join(code) % self.GetTranslation({ 'var' : var_name })
1245275970Scy
1246275970Scy        return code.split('\n')
1247275970Scy
1248275970Scy    def CodeClear(self, structname):
1249275970Scy        translate = self.GetTranslation({ 'structname' : structname })
1250275970Scy        codearrayfree = self._entry.CodeArrayFree(
1251275970Scy            '%(structname)s->%(name)s_data[i]' % self.GetTranslation(
1252275970Scy            { 'structname' : structname } ))
1253275970Scy
1254275970Scy        code = [ 'if (%(structname)s->%(name)s_set == 1) {' ]
1255275970Scy
1256275970Scy        if codearrayfree:
1257275970Scy            code += [
1258275970Scy                '  int i;',
1259275970Scy                '  for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ]
1260275970Scy
1261275970Scy        code = TranslateList(code, translate)
1262275970Scy
1263275970Scy        if codearrayfree:
1264275970Scy            code += map(lambda x: '    ' + x, codearrayfree)
1265275970Scy            code += [
1266275970Scy                '  }' ]
1267275970Scy
1268275970Scy        code += TranslateList([
1269275970Scy                 '  free(%(structname)s->%(name)s_data);',
1270275970Scy                 '  %(structname)s->%(name)s_data = NULL;',
1271275970Scy                 '  %(structname)s->%(name)s_set = 0;',
1272275970Scy                 '  %(structname)s->%(name)s_length = 0;',
1273275970Scy                 '  %(structname)s->%(name)s_num_allocated = 0;',
1274275970Scy                 '}'
1275275970Scy                 ], translate)
1276275970Scy
1277275970Scy        return code
1278275970Scy
1279275970Scy    def CodeInitialize(self, name):
1280275970Scy        code  = ['%s->%s_data = NULL;' % (name, self._name),
1281275970Scy                 '%s->%s_length = 0;' % (name, self._name),
1282275970Scy                 '%s->%s_num_allocated = 0;' % (name, self._name)]
1283275970Scy        return code
1284275970Scy
1285275970Scy    def CodeFree(self, structname):
1286275970Scy        code = self.CodeClear(structname);
1287275970Scy
1288275970Scy        code += TranslateList([
1289275970Scy            'free(%(structname)s->%(name)s_data);' ],
1290275970Scy                              self.GetTranslation({'structname' : structname }))
1291275970Scy
1292275970Scy        return code
1293275970Scy
1294275970Scy    def Declaration(self):
1295275970Scy        dcl  = ['%s *%s_data;' % (self._ctype, self._name),
1296275970Scy                'int %s_length;' % self._name,
1297275970Scy                'int %s_num_allocated;' % self._name ]
1298275970Scy
1299275970Scy        return dcl
1300275970Scy
1301275970Scydef NormalizeLine(line):
1302275970Scy    global white
1303275970Scy    global cppcomment
1304275970Scy
1305275970Scy    line = cppcomment.sub('', line)
1306275970Scy    line = line.strip()
1307275970Scy    line = white.sub(' ', line)
1308275970Scy
1309275970Scy    return line
1310275970Scy
1311275970Scydef ProcessOneEntry(factory, newstruct, entry):
1312275970Scy    optional = 0
1313275970Scy    array = 0
1314275970Scy    entry_type = ''
1315275970Scy    name = ''
1316275970Scy    tag = ''
1317275970Scy    tag_set = None
1318275970Scy    separator = ''
1319275970Scy    fixed_length = ''
1320275970Scy
1321275970Scy    tokens = entry.split(' ')
1322275970Scy    while tokens:
1323275970Scy        token = tokens[0]
1324275970Scy        tokens = tokens[1:]
1325275970Scy
1326275970Scy        if not entry_type:
1327275970Scy            if not optional and token == 'optional':
1328275970Scy                optional = 1
1329275970Scy                continue
1330275970Scy
1331275970Scy            if not array and token == 'array':
1332275970Scy                array = 1
1333275970Scy                continue
1334275970Scy
1335275970Scy        if not entry_type:
1336275970Scy            entry_type = token
1337275970Scy            continue
1338275970Scy
1339275970Scy        if not name:
1340275970Scy            res = re.match(r'^([^\[\]]+)(\[.*\])?$', token)
1341275970Scy            if not res:
1342275970Scy                 raise RpcGenError(
1343275970Scy                     'Cannot parse name: \"%s\" '
1344275970Scy                     'around line %d' % (entry, line_count))
1345275970Scy            name = res.group(1)
1346275970Scy            fixed_length = res.group(2)
1347275970Scy            if fixed_length:
1348275970Scy                fixed_length = fixed_length[1:-1]
1349275970Scy            continue
1350275970Scy
1351275970Scy        if not separator:
1352275970Scy            separator = token
1353275970Scy            if separator != '=':
1354275970Scy                 raise RpcGenError('Expected "=" after name \"%s\" got %s'
1355275970Scy                                   % (name, token))
1356275970Scy            continue
1357275970Scy
1358275970Scy        if not tag_set:
1359275970Scy            tag_set = 1
1360275970Scy            if not re.match(r'^(0x)?[0-9]+$', token):
1361275970Scy                raise RpcGenError('Expected tag number: \"%s\"' % entry)
1362275970Scy            tag = int(token, 0)
1363275970Scy            continue
1364275970Scy
1365275970Scy        raise RpcGenError('Cannot parse \"%s\"' % entry)
1366275970Scy
1367275970Scy    if not tag_set:
1368275970Scy        raise RpcGenError('Need tag number: \"%s\"' % entry)
1369275970Scy
1370275970Scy    # Create the right entry
1371275970Scy    if entry_type == 'bytes':
1372275970Scy        if fixed_length:
1373275970Scy            newentry = factory.EntryBytes(entry_type, name, tag, fixed_length)
1374275970Scy        else:
1375275970Scy            newentry = factory.EntryVarBytes(entry_type, name, tag)
1376275970Scy    elif entry_type == 'int' and not fixed_length:
1377275970Scy        newentry = factory.EntryInt(entry_type, name, tag)
1378275970Scy    elif entry_type == 'int64' and not fixed_length:
1379275970Scy        newentry = factory.EntryInt(entry_type, name, tag, bits=64)
1380275970Scy    elif entry_type == 'string' and not fixed_length:
1381275970Scy        newentry = factory.EntryString(entry_type, name, tag)
1382275970Scy    else:
1383275970Scy        res = structref.match(entry_type)
1384275970Scy        if res:
1385275970Scy            # References another struct defined in our file
1386275970Scy            newentry = factory.EntryStruct(entry_type, name, tag, res.group(1))
1387275970Scy        else:
1388275970Scy            raise RpcGenError('Bad type: "%s" in "%s"' % (entry_type, entry))
1389275970Scy
1390275970Scy    structs = []
1391275970Scy
1392275970Scy    if optional:
1393275970Scy        newentry.MakeOptional()
1394275970Scy    if array:
1395275970Scy        newentry.MakeArray()
1396275970Scy
1397275970Scy    newentry.SetStruct(newstruct)
1398275970Scy    newentry.SetLineCount(line_count)
1399275970Scy    newentry.Verify()
1400275970Scy
1401275970Scy    if array:
1402275970Scy        # We need to encapsulate this entry into a struct
1403275970Scy        newname = newentry.Name()+ '_array'
1404275970Scy
1405275970Scy        # Now borgify the new entry.
1406275970Scy        newentry = factory.EntryArray(newentry)
1407275970Scy        newentry.SetStruct(newstruct)
1408275970Scy        newentry.SetLineCount(line_count)
1409275970Scy        newentry.MakeArray()
1410275970Scy
1411275970Scy    newstruct.AddEntry(newentry)
1412275970Scy
1413275970Scy    return structs
1414275970Scy
1415275970Scydef ProcessStruct(factory, data):
1416275970Scy    tokens = data.split(' ')
1417275970Scy
1418275970Scy    # First three tokens are: 'struct' 'name' '{'
1419275970Scy    newstruct = factory.Struct(tokens[1])
1420275970Scy
1421275970Scy    inside = ' '.join(tokens[3:-1])
1422275970Scy
1423275970Scy    tokens = inside.split(';')
1424275970Scy
1425275970Scy    structs = []
1426275970Scy
1427275970Scy    for entry in tokens:
1428275970Scy        entry = NormalizeLine(entry)
1429275970Scy        if not entry:
1430275970Scy            continue
1431275970Scy
1432275970Scy        # It's possible that new structs get defined in here
1433275970Scy        structs.extend(ProcessOneEntry(factory, newstruct, entry))
1434275970Scy
1435275970Scy    structs.append(newstruct)
1436275970Scy    return structs
1437275970Scy
1438275970Scydef GetNextStruct(file):
1439275970Scy    global line_count
1440275970Scy    global cppdirect
1441275970Scy
1442275970Scy    got_struct = 0
1443275970Scy
1444275970Scy    processed_lines = []
1445275970Scy
1446275970Scy    have_c_comment = 0
1447275970Scy    data = ''
1448275970Scy    while 1:
1449275970Scy        line = file.readline()
1450275970Scy        if not line:
1451275970Scy            break
1452275970Scy
1453275970Scy        line_count += 1
1454275970Scy        line = line[:-1]
1455275970Scy
1456275970Scy        if not have_c_comment and re.search(r'/\*', line):
1457275970Scy            if re.search(r'/\*.*?\*/', line):
1458275970Scy                line = re.sub(r'/\*.*?\*/', '', line)
1459275970Scy            else:
1460275970Scy                line = re.sub(r'/\*.*$', '', line)
1461275970Scy                have_c_comment = 1
1462275970Scy
1463275970Scy        if have_c_comment:
1464275970Scy            if not re.search(r'\*/', line):
1465275970Scy                continue
1466275970Scy            have_c_comment = 0
1467275970Scy            line = re.sub(r'^.*\*/', '', line)
1468275970Scy
1469275970Scy        line = NormalizeLine(line)
1470275970Scy
1471275970Scy        if not line:
1472275970Scy            continue
1473275970Scy
1474275970Scy        if not got_struct:
1475275970Scy            if re.match(r'#include ["<].*[>"]', line):
1476275970Scy                cppdirect.append(line)
1477275970Scy                continue
1478275970Scy
1479275970Scy            if re.match(r'^#(if( |def)|endif)', line):
1480275970Scy                cppdirect.append(line)
1481275970Scy                continue
1482275970Scy
1483275970Scy            if re.match(r'^#define', line):
1484275970Scy                headerdirect.append(line)
1485275970Scy                continue
1486275970Scy
1487275970Scy            if not structdef.match(line):
1488275970Scy                raise RpcGenError('Missing struct on line %d: %s'
1489275970Scy                                  % (line_count, line))
1490275970Scy            else:
1491275970Scy                got_struct = 1
1492275970Scy                data += line
1493275970Scy            continue
1494275970Scy
1495275970Scy        # We are inside the struct
1496275970Scy        tokens = line.split('}')
1497275970Scy        if len(tokens) == 1:
1498275970Scy            data += ' ' + line
1499275970Scy            continue
1500275970Scy
1501275970Scy        if len(tokens[1]):
1502275970Scy            raise RpcGenError('Trailing garbage after struct on line %d'
1503275970Scy                              % line_count)
1504275970Scy
1505275970Scy        # We found the end of the struct
1506275970Scy        data += ' %s}' % tokens[0]
1507275970Scy        break
1508275970Scy
1509275970Scy    # Remove any comments, that might be in there
1510275970Scy    data = re.sub(r'/\*.*\*/', '', data)
1511275970Scy
1512275970Scy    return data
1513275970Scy
1514275970Scy
1515275970Scydef Parse(factory, file):
1516275970Scy    """
1517275970Scy    Parses the input file and returns C code and corresponding header file.
1518275970Scy    """
1519275970Scy
1520275970Scy    entities = []
1521275970Scy
1522275970Scy    while 1:
1523275970Scy        # Just gets the whole struct nicely formatted
1524275970Scy        data = GetNextStruct(file)
1525275970Scy
1526275970Scy        if not data:
1527275970Scy            break
1528275970Scy
1529275970Scy        entities.extend(ProcessStruct(factory, data))
1530275970Scy
1531275970Scy    return entities
1532275970Scy
1533275970Scyclass CCodeGenerator:
1534275970Scy    def __init__(self):
1535275970Scy        pass
1536275970Scy
1537275970Scy    def GuardName(self, name):
1538275970Scy        # Use the complete provided path to the input file, with all
1539275970Scy        # non-identifier characters replaced with underscores, to
1540275970Scy        # reduce the chance of a collision between guard macros.
1541275970Scy        return 'EVENT_RPCOUT_' + nonident.sub('_', name).upper() + '_'
1542275970Scy
1543275970Scy    def HeaderPreamble(self, name):
1544275970Scy        guard = self.GuardName(name)
1545275970Scy        pre = (
1546275970Scy            '/*\n'
1547275970Scy            ' * Automatically generated from %s\n'
1548275970Scy            ' */\n\n'
1549275970Scy            '#ifndef %s\n'
1550275970Scy            '#define %s\n\n' ) % (
1551275970Scy            name, guard, guard)
1552275970Scy
1553275970Scy        for statement in headerdirect:
1554275970Scy            pre += '%s\n' % statement
1555275970Scy        if headerdirect:
1556275970Scy            pre += '\n'
1557275970Scy
1558275970Scy        pre += (
1559275970Scy            '#include <event2/util.h> /* for ev_uint*_t */\n'
1560275970Scy            '#include <event2/rpc.h>\n'
1561275970Scy        )
1562275970Scy
1563275970Scy        return pre
1564275970Scy
1565275970Scy    def HeaderPostamble(self, name):
1566275970Scy        guard = self.GuardName(name)
1567275970Scy        return '#endif  /* %s */' % guard
1568275970Scy
1569275970Scy    def BodyPreamble(self, name, header_file):
1570275970Scy        global _NAME
1571275970Scy        global _VERSION
1572275970Scy
1573275970Scy        slash = header_file.rfind('/')
1574275970Scy        if slash != -1:
1575275970Scy            header_file = header_file[slash+1:]
1576275970Scy
1577275970Scy        pre = ( '/*\n'
1578275970Scy                ' * Automatically generated from %s\n'
1579275970Scy                ' * by %s/%s.  DO NOT EDIT THIS FILE.\n'
1580275970Scy                ' */\n\n' ) % (name, _NAME, _VERSION)
1581275970Scy        pre += ( '#include <stdlib.h>\n'
1582275970Scy                 '#include <string.h>\n'
1583275970Scy                 '#include <assert.h>\n'
1584275970Scy                 '#include <event2/event-config.h>\n'
1585275970Scy                 '#include <event2/event.h>\n'
1586275970Scy                 '#include <event2/buffer.h>\n'
1587275970Scy                 '#include <event2/tag.h>\n\n'
1588275970Scy                 '#ifdef EVENT____func__\n'
1589275970Scy                 '#define __func__ EVENT____func__\n'
1590275970Scy                 '#endif\n\n'
1591275970Scy                 )
1592275970Scy
1593275970Scy        for statement in cppdirect:
1594275970Scy            pre += '%s\n' % statement
1595275970Scy
1596275970Scy        pre += '\n#include "%s"\n\n' % header_file
1597275970Scy
1598275970Scy        pre += 'void event_warn(const char *fmt, ...);\n'
1599275970Scy        pre += 'void event_warnx(const char *fmt, ...);\n\n'
1600275970Scy
1601275970Scy        return pre
1602275970Scy
1603275970Scy    def HeaderFilename(self, filename):
1604275970Scy        return '.'.join(filename.split('.')[:-1]) + '.h'
1605275970Scy
1606275970Scy    def CodeFilename(self, filename):
1607275970Scy        return '.'.join(filename.split('.')[:-1]) + '.gen.c'
1608275970Scy
1609275970Scy    def Struct(self, name):
1610275970Scy        return StructCCode(name)
1611275970Scy
1612275970Scy    def EntryBytes(self, entry_type, name, tag, fixed_length):
1613275970Scy        return EntryBytes(entry_type, name, tag, fixed_length)
1614275970Scy
1615275970Scy    def EntryVarBytes(self, entry_type, name, tag):
1616275970Scy        return EntryVarBytes(entry_type, name, tag)
1617275970Scy
1618275970Scy    def EntryInt(self, entry_type, name, tag, bits=32):
1619275970Scy        return EntryInt(entry_type, name, tag, bits)
1620275970Scy
1621275970Scy    def EntryString(self, entry_type, name, tag):
1622275970Scy        return EntryString(entry_type, name, tag)
1623275970Scy
1624275970Scy    def EntryStruct(self, entry_type, name, tag, struct_name):
1625275970Scy        return EntryStruct(entry_type, name, tag, struct_name)
1626275970Scy
1627275970Scy    def EntryArray(self, entry):
1628275970Scy        return EntryArray(entry)
1629275970Scy
1630275970Scyclass Usage(RpcGenError):
1631275970Scy    def __init__(self, argv0):
1632275970Scy        RpcGenError.__init__("usage: %s input.rpc [[output.h] output.c]"
1633275970Scy                             % argv0)
1634275970Scy
1635275970Scyclass CommandLine:
1636275970Scy    def __init__(self, argv):
1637275970Scy        """Initialize a command-line to launch event_rpcgen, as if
1638275970Scy           from a command-line with CommandLine(sys.argv).  If you're
1639275970Scy           calling this directly, remember to provide a dummy value
1640275970Scy           for sys.argv[0]
1641275970Scy        """
1642275970Scy        self.filename = None
1643275970Scy        self.header_file = None
1644275970Scy        self.impl_file = None
1645275970Scy        self.factory = CCodeGenerator()
1646275970Scy
1647275970Scy        if len(argv) >= 2 and argv[1] == '--quiet':
1648275970Scy            global QUIETLY
1649275970Scy            QUIETLY = 1
1650275970Scy            del argv[1]
1651275970Scy
1652275970Scy        if len(argv) < 2 or len(argv) > 4:
1653275970Scy            raise Usage(argv[0])
1654275970Scy
1655275970Scy        self.filename = argv[1].replace('\\', '/')
1656275970Scy        if len(argv) == 3:
1657275970Scy            self.impl_file = argv[2].replace('\\', '/')
1658275970Scy        if len(argv) == 4:
1659275970Scy            self.header_file = argv[2].replace('\\', '/')
1660275970Scy            self.impl_file = argv[3].replace('\\', '/')
1661275970Scy
1662275970Scy        if not self.filename:
1663275970Scy            raise Usage(argv[0])
1664275970Scy
1665275970Scy        if not self.impl_file:
1666275970Scy            self.impl_file = self.factory.CodeFilename(self.filename)
1667275970Scy
1668275970Scy        if not self.header_file:
1669275970Scy            self.header_file = self.factory.HeaderFilename(self.impl_file)
1670275970Scy
1671275970Scy        if not self.impl_file.endswith('.c'):
1672275970Scy            raise RpcGenError("can only generate C implementation files")
1673275970Scy        if not self.header_file.endswith('.h'):
1674275970Scy            raise RpcGenError("can only generate C header files")
1675275970Scy
1676275970Scy    def run(self):
1677275970Scy        filename = self.filename
1678275970Scy        header_file = self.header_file
1679275970Scy        impl_file = self.impl_file
1680275970Scy        factory = self.factory
1681275970Scy
1682275970Scy        declare('Reading \"%s\"' % filename)
1683275970Scy
1684275970Scy        fp = open(filename, 'r')
1685275970Scy        entities = Parse(factory, fp)
1686275970Scy        fp.close()
1687275970Scy
1688275970Scy        declare('... creating "%s"' % header_file)
1689275970Scy        header_fp = open(header_file, 'w')
1690275970Scy        print >>header_fp, factory.HeaderPreamble(filename)
1691275970Scy
1692275970Scy        # Create forward declarations: allows other structs to reference
1693275970Scy        # each other
1694275970Scy        for entry in entities:
1695275970Scy            entry.PrintForwardDeclaration(header_fp)
1696275970Scy        print >>header_fp, ''
1697275970Scy
1698275970Scy        for entry in entities:
1699275970Scy            entry.PrintTags(header_fp)
1700275970Scy            entry.PrintDeclaration(header_fp)
1701275970Scy        print >>header_fp, factory.HeaderPostamble(filename)
1702275970Scy        header_fp.close()
1703275970Scy
1704275970Scy        declare('... creating "%s"' % impl_file)
1705275970Scy        impl_fp = open(impl_file, 'w')
1706275970Scy        print >>impl_fp, factory.BodyPreamble(filename, header_file)
1707275970Scy        for entry in entities:
1708275970Scy            entry.PrintCode(impl_fp)
1709275970Scy        impl_fp.close()
1710275970Scy
1711275970Scyif __name__ == '__main__':
1712275970Scy    try:
1713275970Scy        CommandLine(sys.argv).run()
1714275970Scy        sys.exit(0)
1715275970Scy
1716275970Scy    except RpcGenError, e:
1717275970Scy        print >>sys.stderr, e
1718275970Scy        sys.exit(1)
1719275970Scy
1720275970Scy    except EnvironmentError, e:
1721275970Scy        if e.filename and e.strerror:
1722275970Scy            print >>sys.stderr, "%s: %s" % (e.filename, e.strerror)
1723275970Scy            sys.exit(1)
1724275970Scy        elif e.strerror:
1725275970Scy            print >> sys.stderr, e.strerror
1726275970Scy            sys.exit(1)
1727275970Scy        else:
1728275970Scy            raise
1729