ipc/chromium/src/third_party/libevent/event_rpcgen.py

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/chromium/src/third_party/libevent/event_rpcgen.py	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1717 @@
     1.4 +#!/usr/bin/env python2
     1.5 +#
     1.6 +# Copyright (c) 2005-2007 Niels Provos <provos@citi.umich.edu>
     1.7 +# Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
     1.8 +# All rights reserved.
     1.9 +#
    1.10 +# Generates marshaling code based on libevent.
    1.11 +
    1.12 +# TODO:
    1.13 +# 1) use optparse to allow the strategy shell to parse options, and
    1.14 +#    to allow the instantiated factory (for the specific output language)
    1.15 +#    to parse remaining options
    1.16 +# 2) move the globals into a class that manages execution (including the
    1.17 +#    progress outputs that space stderr at the moment)
    1.18 +# 3) emit other languages
    1.19 +
    1.20 +import sys
    1.21 +import re
    1.22 +
    1.23 +_NAME = "event_rpcgen.py"
    1.24 +_VERSION = "0.1"
    1.25 +
    1.26 +# Globals
    1.27 +line_count = 0
    1.28 +
    1.29 +white = re.compile(r'\s+')
    1.30 +cppcomment = re.compile(r'\/\/.*$')
    1.31 +nonident = re.compile(r'[^a-zA-Z0-9_]')
    1.32 +structref = re.compile(r'^struct\[([a-zA-Z_][a-zA-Z0-9_]*)\]$')
    1.33 +structdef = re.compile(r'^struct +[a-zA-Z_][a-zA-Z0-9_]* *{$')
    1.34 +
    1.35 +headerdirect = []
    1.36 +cppdirect = []
    1.37 +
    1.38 +def TranslateList(mylist, mydict):
    1.39 +    return map(lambda x: x % mydict, mylist)
    1.40 +
    1.41 +# Exception class for parse errors
    1.42 +class RpcGenError(Exception):
    1.43 +        def __init__(self, why):
    1.44 +                self.why = why
    1.45 +        def __str__(self):
    1.46 +                return str(self.why)
    1.47 +
    1.48 +# Holds everything that makes a struct
    1.49 +class Struct:
    1.50 +    def __init__(self, name):
    1.51 +        self._name = name
    1.52 +        self._entries = []
    1.53 +        self._tags = {}
    1.54 +        print >>sys.stderr, '  Created struct: %s' % name
    1.55 +
    1.56 +    def AddEntry(self, entry):
    1.57 +        if self._tags.has_key(entry.Tag()):
    1.58 +            raise RpcGenError(
    1.59 +                'Entry "%s" duplicates tag number %d from "%s" '
    1.60 +                'around line %d' % (entry.Name(), entry.Tag(),
    1.61 +                                    self._tags[entry.Tag()], line_count))
    1.62 +        self._entries.append(entry)
    1.63 +        self._tags[entry.Tag()] = entry.Name()
    1.64 +        print >>sys.stderr, '    Added entry: %s' % entry.Name()
    1.65 +
    1.66 +    def Name(self):
    1.67 +        return self._name
    1.68 +
    1.69 +    def EntryTagName(self, entry):
    1.70 +        """Creates the name inside an enumeration for distinguishing data
    1.71 +        types."""
    1.72 +        name = "%s_%s" % (self._name, entry.Name())
    1.73 +        return name.upper()
    1.74 +
    1.75 +    def PrintIndented(self, file, ident, code):
    1.76 +        """Takes an array, add indentation to each entry and prints it."""
    1.77 +        for entry in code:
    1.78 +            print >>file, '%s%s' % (ident, entry)
    1.79 +
    1.80 +class StructCCode(Struct):
    1.81 +    """ Knows how to generate C code for a struct """
    1.82 +
    1.83 +    def __init__(self, name):
    1.84 +        Struct.__init__(self, name)
    1.85 +
    1.86 +    def PrintTags(self, file):
    1.87 +        """Prints the tag definitions for a structure."""
    1.88 +        print >>file, '/* Tag definition for %s */' % self._name
    1.89 +        print >>file, 'enum %s_ {' % self._name.lower()
    1.90 +        for entry in self._entries:
    1.91 +            print >>file, '  %s=%d,' % (self.EntryTagName(entry),
    1.92 +                                        entry.Tag())
    1.93 +        print >>file, '  %s_MAX_TAGS' % (self._name.upper())
    1.94 +        print >>file, '};\n'
    1.95 +
    1.96 +    def PrintForwardDeclaration(self, file):
    1.97 +        print >>file, 'struct %s;' % self._name
    1.98 +
    1.99 +    def PrintDeclaration(self, file):
   1.100 +        print >>file, '/* Structure declaration for %s */' % self._name
   1.101 +        print >>file, 'struct %s_access_ {' % self._name
   1.102 +        for entry in self._entries:
   1.103 +            dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name())
   1.104 +            dcl.extend(
   1.105 +                entry.GetDeclaration('(*%s_get)' % entry.Name()))
   1.106 +            if entry.Array():
   1.107 +                dcl.extend(
   1.108 +                    entry.AddDeclaration('(*%s_add)' % entry.Name()))
   1.109 +            self.PrintIndented(file, '  ', dcl)
   1.110 +        print >>file, '};\n'
   1.111 +
   1.112 +        print >>file, 'struct %s {' % self._name
   1.113 +        print >>file, '  struct %s_access_ *base;\n' % self._name
   1.114 +        for entry in self._entries:
   1.115 +            dcl = entry.Declaration()
   1.116 +            self.PrintIndented(file, '  ', dcl)
   1.117 +        print >>file, ''
   1.118 +        for entry in self._entries:
   1.119 +            print >>file, '  ev_uint8_t %s_set;' % entry.Name()
   1.120 +        print >>file, '};\n'
   1.121 +
   1.122 +        print >>file, \
   1.123 +"""struct %(name)s *%(name)s_new(void);
   1.124 +struct %(name)s *%(name)s_new_with_arg(void *);
   1.125 +void %(name)s_free(struct %(name)s *);
   1.126 +void %(name)s_clear(struct %(name)s *);
   1.127 +void %(name)s_marshal(struct evbuffer *, const struct %(name)s *);
   1.128 +int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *);
   1.129 +int %(name)s_complete(struct %(name)s *);
   1.130 +void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t,
   1.131 +    const struct %(name)s *);
   1.132 +int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
   1.133 +    struct %(name)s *);""" % { 'name' : self._name }
   1.134 +
   1.135 +
   1.136 +        # Write a setting function of every variable
   1.137 +        for entry in self._entries:
   1.138 +            self.PrintIndented(file, '', entry.AssignDeclaration(
   1.139 +                entry.AssignFuncName()))
   1.140 +            self.PrintIndented(file, '', entry.GetDeclaration(
   1.141 +                entry.GetFuncName()))
   1.142 +            if entry.Array():
   1.143 +                self.PrintIndented(file, '', entry.AddDeclaration(
   1.144 +                    entry.AddFuncName()))
   1.145 +
   1.146 +        print >>file, '/* --- %s done --- */\n' % self._name
   1.147 +
   1.148 +    def PrintCode(self, file):
   1.149 +        print >>file, ('/*\n'
   1.150 +                       ' * Implementation of %s\n'
   1.151 +                       ' */\n') % self._name
   1.152 +
   1.153 +        print >>file, \
   1.154 +              'static struct %(name)s_access_ __%(name)s_base = {' % \
   1.155 +              { 'name' : self._name }
   1.156 +        for entry in self._entries:
   1.157 +            self.PrintIndented(file, '  ', entry.CodeBase())
   1.158 +        print >>file, '};\n'
   1.159 +
   1.160 +        # Creation
   1.161 +        print >>file, (
   1.162 +            'struct %(name)s *\n'
   1.163 +            '%(name)s_new(void)\n'
   1.164 +            '{\n'
   1.165 +            '  return %(name)s_new_with_arg(NULL);\n'
   1.166 +            '}\n'
   1.167 +            '\n'
   1.168 +            'struct %(name)s *\n'
   1.169 +            '%(name)s_new_with_arg(void *unused)\n'
   1.170 +            '{\n'
   1.171 +            '  struct %(name)s *tmp;\n'
   1.172 +            '  if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n'
   1.173 +            '    event_warn("%%s: malloc", __func__);\n'
   1.174 +            '    return (NULL);\n'
   1.175 +            '  }\n'
   1.176 +            '  tmp->base = &__%(name)s_base;\n') % { 'name' : self._name }
   1.177 +
   1.178 +        for entry in self._entries:
   1.179 +            self.PrintIndented(file, '  ', entry.CodeInitialize('tmp'))
   1.180 +            print >>file, '  tmp->%s_set = 0;\n' % entry.Name()
   1.181 +
   1.182 +        print >>file, (
   1.183 +            '  return (tmp);\n'
   1.184 +            '}\n')
   1.185 +
   1.186 +        # Adding
   1.187 +        for entry in self._entries:
   1.188 +            if entry.Array():
   1.189 +                self.PrintIndented(file, '', entry.CodeAdd())
   1.190 +            print >>file, ''
   1.191 +
   1.192 +        # Assigning
   1.193 +        for entry in self._entries:
   1.194 +            self.PrintIndented(file, '', entry.CodeAssign())
   1.195 +            print >>file, ''
   1.196 +
   1.197 +        # Getting
   1.198 +        for entry in self._entries:
   1.199 +            self.PrintIndented(file, '', entry.CodeGet())
   1.200 +            print >>file, ''
   1.201 +
   1.202 +        # Clearing
   1.203 +        print >>file, ( 'void\n'
   1.204 +                        '%(name)s_clear(struct %(name)s *tmp)\n'
   1.205 +                        '{'
   1.206 +                        ) % { 'name' : self._name }
   1.207 +        for entry in self._entries:
   1.208 +            self.PrintIndented(file, '  ', entry.CodeClear('tmp'))
   1.209 +
   1.210 +        print >>file, '}\n'
   1.211 +
   1.212 +        # Freeing
   1.213 +        print >>file, ( 'void\n'
   1.214 +                        '%(name)s_free(struct %(name)s *tmp)\n'
   1.215 +                        '{'
   1.216 +                        ) % { 'name' : self._name }
   1.217 +
   1.218 +        for entry in self._entries:
   1.219 +            self.PrintIndented(file, '  ', entry.CodeFree('tmp'))
   1.220 +
   1.221 +        print >>file, ('  free(tmp);\n'
   1.222 +                       '}\n')
   1.223 +
   1.224 +        # Marshaling
   1.225 +        print >>file, ('void\n'
   1.226 +                       '%(name)s_marshal(struct evbuffer *evbuf, '
   1.227 +                       'const struct %(name)s *tmp)'
   1.228 +                       '{') % { 'name' : self._name }
   1.229 +        for entry in self._entries:
   1.230 +            indent = '  '
   1.231 +            # Optional entries do not have to be set
   1.232 +            if entry.Optional():
   1.233 +                indent += '  '
   1.234 +                print >>file, '  if (tmp->%s_set) {' % entry.Name()
   1.235 +            self.PrintIndented(
   1.236 +                file, indent,
   1.237 +                entry.CodeMarshal('evbuf', self.EntryTagName(entry),
   1.238 +                                  entry.GetVarName('tmp'),
   1.239 +                                  entry.GetVarLen('tmp')))
   1.240 +            if entry.Optional():
   1.241 +                print >>file, '  }'
   1.242 +
   1.243 +        print >>file, '}\n'
   1.244 +
   1.245 +        # Unmarshaling
   1.246 +        print >>file, ('int\n'
   1.247 +                       '%(name)s_unmarshal(struct %(name)s *tmp, '
   1.248 +                       ' struct evbuffer *evbuf)\n'
   1.249 +                       '{\n'
   1.250 +                       '  ev_uint32_t tag;\n'
   1.251 +                       '  while (evbuffer_get_length(evbuf) > 0) {\n'
   1.252 +                       '    if (evtag_peek(evbuf, &tag) == -1)\n'
   1.253 +                       '      return (-1);\n'
   1.254 +                       '    switch (tag) {\n'
   1.255 +                       ) % { 'name' : self._name }
   1.256 +        for entry in self._entries:
   1.257 +            print >>file, '      case %s:\n' % self.EntryTagName(entry)
   1.258 +            if not entry.Array():
   1.259 +                print >>file, (
   1.260 +                    '        if (tmp->%s_set)\n'
   1.261 +                    '          return (-1);'
   1.262 +                    ) % (entry.Name())
   1.263 +
   1.264 +            self.PrintIndented(
   1.265 +                file, '        ',
   1.266 +                entry.CodeUnmarshal('evbuf',
   1.267 +                                    self.EntryTagName(entry),
   1.268 +                                    entry.GetVarName('tmp'),
   1.269 +                                    entry.GetVarLen('tmp')))
   1.270 +
   1.271 +            print >>file, ( '        tmp->%s_set = 1;\n' % entry.Name() +
   1.272 +                            '        break;\n' )
   1.273 +        print >>file, ( '      default:\n'
   1.274 +                        '        return -1;\n'
   1.275 +                        '    }\n'
   1.276 +                        '  }\n' )
   1.277 +        # Check if it was decoded completely
   1.278 +        print >>file, ( '  if (%(name)s_complete(tmp) == -1)\n'
   1.279 +                        '    return (-1);'
   1.280 +                        ) % { 'name' : self._name }
   1.281 +
   1.282 +        # Successfully decoded
   1.283 +        print >>file, ( '  return (0);\n'
   1.284 +                        '}\n')
   1.285 +
   1.286 +        # Checking if a structure has all the required data
   1.287 +        print >>file, (
   1.288 +            'int\n'
   1.289 +            '%(name)s_complete(struct %(name)s *msg)\n'
   1.290 +            '{' ) % { 'name' : self._name }
   1.291 +        for entry in self._entries:
   1.292 +            if not entry.Optional():
   1.293 +                code = [
   1.294 +                    'if (!msg->%(name)s_set)',
   1.295 +                    '  return (-1);' ]
   1.296 +                code = TranslateList(code, entry.GetTranslation())
   1.297 +                self.PrintIndented(
   1.298 +                    file, '  ', code)
   1.299 +
   1.300 +            self.PrintIndented(
   1.301 +                file, '  ',
   1.302 +                entry.CodeComplete('msg', entry.GetVarName('msg')))
   1.303 +        print >>file, (
   1.304 +            '  return (0);\n'
   1.305 +            '}\n' )
   1.306 +
   1.307 +        # Complete message unmarshaling
   1.308 +        print >>file, (
   1.309 +            'int\n'
   1.310 +            'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, '
   1.311 +            'ev_uint32_t need_tag, struct %(name)s *msg)\n'
   1.312 +            '{\n'
   1.313 +            '  ev_uint32_t tag;\n'
   1.314 +            '  int res = -1;\n'
   1.315 +            '\n'
   1.316 +            '  struct evbuffer *tmp = evbuffer_new();\n'
   1.317 +            '\n'
   1.318 +            '  if (evtag_unmarshal(evbuf, &tag, tmp) == -1'
   1.319 +            ' || tag != need_tag)\n'
   1.320 +            '    goto error;\n'
   1.321 +            '\n'
   1.322 +            '  if (%(name)s_unmarshal(msg, tmp) == -1)\n'
   1.323 +            '    goto error;\n'
   1.324 +            '\n'
   1.325 +            '  res = 0;\n'
   1.326 +            '\n'
   1.327 +            ' error:\n'
   1.328 +            '  evbuffer_free(tmp);\n'
   1.329 +            '  return (res);\n'
   1.330 +            '}\n' ) % { 'name' : self._name }
   1.331 +
   1.332 +        # Complete message marshaling
   1.333 +        print >>file, (
   1.334 +            'void\n'
   1.335 +            'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, '
   1.336 +            'const struct %(name)s *msg)\n'
   1.337 +            '{\n'
   1.338 +            '  struct evbuffer *_buf = evbuffer_new();\n'
   1.339 +            '  assert(_buf != NULL);\n'
   1.340 +            '  %(name)s_marshal(_buf, msg);\n'
   1.341 +            '  evtag_marshal_buffer(evbuf, tag, _buf);\n '
   1.342 +            '  evbuffer_free(_buf);\n'
   1.343 +            '}\n' ) % { 'name' : self._name }
   1.344 +
   1.345 +class Entry:
   1.346 +    def __init__(self, type, name, tag):
   1.347 +        self._type = type
   1.348 +        self._name = name
   1.349 +        self._tag = int(tag)
   1.350 +        self._ctype = type
   1.351 +        self._optional = 0
   1.352 +        self._can_be_array = 0
   1.353 +        self._array = 0
   1.354 +        self._line_count = -1
   1.355 +        self._struct = None
   1.356 +        self._refname = None
   1.357 +
   1.358 +        self._optpointer = True
   1.359 +        self._optaddarg = True
   1.360 +
   1.361 +    def GetInitializer(self):
   1.362 +        assert 0, "Entry does not provide initializer"
   1.363 +
   1.364 +    def SetStruct(self, struct):
   1.365 +        self._struct = struct
   1.366 +
   1.367 +    def LineCount(self):
   1.368 +        assert self._line_count != -1
   1.369 +        return self._line_count
   1.370 +
   1.371 +    def SetLineCount(self, number):
   1.372 +        self._line_count = number
   1.373 +
   1.374 +    def Array(self):
   1.375 +        return self._array
   1.376 +
   1.377 +    def Optional(self):
   1.378 +        return self._optional
   1.379 +
   1.380 +    def Tag(self):
   1.381 +        return self._tag
   1.382 +
   1.383 +    def Name(self):
   1.384 +        return self._name
   1.385 +
   1.386 +    def Type(self):
   1.387 +        return self._type
   1.388 +
   1.389 +    def MakeArray(self, yes=1):
   1.390 +        self._array = yes
   1.391 +
   1.392 +    def MakeOptional(self):
   1.393 +        self._optional = 1
   1.394 +
   1.395 +    def Verify(self):
   1.396 +        if self.Array() and not self._can_be_array:
   1.397 +            raise RpcGenError(
   1.398 +                'Entry "%s" cannot be created as an array '
   1.399 +                'around line %d' % (self._name, self.LineCount()))
   1.400 +        if not self._struct:
   1.401 +            raise RpcGenError(
   1.402 +                'Entry "%s" does not know which struct it belongs to '
   1.403 +                'around line %d' % (self._name, self.LineCount()))
   1.404 +        if self._optional and self._array:
   1.405 +            raise RpcGenError(
   1.406 +                'Entry "%s" has illegal combination of optional and array '
   1.407 +                'around line %d' % (self._name, self.LineCount()))
   1.408 +
   1.409 +    def GetTranslation(self, extradict = {}):
   1.410 +        mapping = {
   1.411 +            "parent_name" : self._struct.Name(),
   1.412 +            "name" : self._name,
   1.413 +            "ctype" : self._ctype,
   1.414 +            "refname" : self._refname,
   1.415 +            "optpointer" : self._optpointer and "*" or "",
   1.416 +            "optreference" : self._optpointer and "&" or "",
   1.417 +            "optaddarg" :
   1.418 +            self._optaddarg and ", const %s value" % self._ctype or ""
   1.419 +            }
   1.420 +        for (k, v) in extradict.items():
   1.421 +            mapping[k] = v
   1.422 +
   1.423 +        return mapping
   1.424 +
   1.425 +    def GetVarName(self, var):
   1.426 +        return '%(var)s->%(name)s_data' % self.GetTranslation({ 'var' : var })
   1.427 +
   1.428 +    def GetVarLen(self, var):
   1.429 +        return 'sizeof(%s)' % self._ctype
   1.430 +
   1.431 +    def GetFuncName(self):
   1.432 +        return '%s_%s_get' % (self._struct.Name(), self._name)
   1.433 +
   1.434 +    def GetDeclaration(self, funcname):
   1.435 +        code = [ 'int %s(struct %s *, %s *);' % (
   1.436 +            funcname, self._struct.Name(), self._ctype ) ]
   1.437 +        return code
   1.438 +
   1.439 +    def CodeGet(self):
   1.440 +        code = (
   1.441 +            'int',
   1.442 +            '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, '
   1.443 +            '%(ctype)s *value)',
   1.444 +            '{',
   1.445 +            '  if (msg->%(name)s_set != 1)',
   1.446 +            '    return (-1);',
   1.447 +            '  *value = msg->%(name)s_data;',
   1.448 +            '  return (0);',
   1.449 +            '}' )
   1.450 +        code = '\n'.join(code)
   1.451 +        code = code % self.GetTranslation()
   1.452 +        return code.split('\n')
   1.453 +
   1.454 +    def AssignFuncName(self):
   1.455 +        return '%s_%s_assign' % (self._struct.Name(), self._name)
   1.456 +
   1.457 +    def AddFuncName(self):
   1.458 +        return '%s_%s_add' % (self._struct.Name(), self._name)
   1.459 +
   1.460 +    def AssignDeclaration(self, funcname):
   1.461 +        code = [ 'int %s(struct %s *, const %s);' % (
   1.462 +            funcname, self._struct.Name(), self._ctype ) ]
   1.463 +        return code
   1.464 +
   1.465 +    def CodeAssign(self):
   1.466 +        code = [ 'int',
   1.467 +                 '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,'
   1.468 +                 ' const %(ctype)s value)',
   1.469 +                 '{',
   1.470 +                 '  msg->%(name)s_set = 1;',
   1.471 +                 '  msg->%(name)s_data = value;',
   1.472 +                 '  return (0);',
   1.473 +                 '}' ]
   1.474 +        code = '\n'.join(code)
   1.475 +        code = code % self.GetTranslation()
   1.476 +        return code.split('\n')
   1.477 +
   1.478 +    def CodeClear(self, structname):
   1.479 +        code = [ '%s->%s_set = 0;' % (structname, self.Name()) ]
   1.480 +
   1.481 +        return code
   1.482 +
   1.483 +    def CodeComplete(self, structname, var_name):
   1.484 +        return []
   1.485 +
   1.486 +    def CodeFree(self, name):
   1.487 +        return []
   1.488 +
   1.489 +    def CodeBase(self):
   1.490 +        code = [
   1.491 +            '%(parent_name)s_%(name)s_assign,',
   1.492 +            '%(parent_name)s_%(name)s_get,'
   1.493 +            ]
   1.494 +        if self.Array():
   1.495 +            code.append('%(parent_name)s_%(name)s_add,')
   1.496 +
   1.497 +        code = '\n'.join(code)
   1.498 +        code = code % self.GetTranslation()
   1.499 +        return code.split('\n')
   1.500 +
   1.501 +class EntryBytes(Entry):
   1.502 +    def __init__(self, type, name, tag, length):
   1.503 +        # Init base class
   1.504 +        Entry.__init__(self, type, name, tag)
   1.505 +
   1.506 +        self._length = length
   1.507 +        self._ctype = 'ev_uint8_t'
   1.508 +
   1.509 +    def GetInitializer(self):
   1.510 +        return "NULL"
   1.511 +
   1.512 +    def GetVarLen(self, var):
   1.513 +        return '(%s)' % self._length
   1.514 +
   1.515 +    def CodeArrayAdd(self, varname, value):
   1.516 +        # XXX: copy here
   1.517 +        return [ '%(varname)s = NULL;' % { 'varname' : varname } ]
   1.518 +
   1.519 +    def GetDeclaration(self, funcname):
   1.520 +        code = [ 'int %s(struct %s *, %s **);' % (
   1.521 +            funcname, self._struct.Name(), self._ctype ) ]
   1.522 +        return code
   1.523 +
   1.524 +    def AssignDeclaration(self, funcname):
   1.525 +        code = [ 'int %s(struct %s *, const %s *);' % (
   1.526 +            funcname, self._struct.Name(), self._ctype ) ]
   1.527 +        return code
   1.528 +
   1.529 +    def Declaration(self):
   1.530 +        dcl  = ['ev_uint8_t %s_data[%s];' % (self._name, self._length)]
   1.531 +
   1.532 +        return dcl
   1.533 +
   1.534 +    def CodeGet(self):
   1.535 +        name = self._name
   1.536 +        code = [ 'int',
   1.537 +                 '%s_%s_get(struct %s *msg, %s **value)' % (
   1.538 +            self._struct.Name(), name,
   1.539 +            self._struct.Name(), self._ctype),
   1.540 +                 '{',
   1.541 +                 '  if (msg->%s_set != 1)' % name,
   1.542 +                 '    return (-1);',
   1.543 +                 '  *value = msg->%s_data;' % name,
   1.544 +                 '  return (0);',
   1.545 +                 '}' ]
   1.546 +        return code
   1.547 +
   1.548 +    def CodeAssign(self):
   1.549 +        name = self._name
   1.550 +        code = [ 'int',
   1.551 +                 '%s_%s_assign(struct %s *msg, const %s *value)' % (
   1.552 +            self._struct.Name(), name,
   1.553 +            self._struct.Name(), self._ctype),
   1.554 +                 '{',
   1.555 +                 '  msg->%s_set = 1;' % name,
   1.556 +                 '  memcpy(msg->%s_data, value, %s);' % (
   1.557 +            name, self._length),
   1.558 +                 '  return (0);',
   1.559 +                 '}' ]
   1.560 +        return code
   1.561 +
   1.562 +    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
   1.563 +        code = [  'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, '
   1.564 +                  '%(var)s, %(varlen)s) == -1) {',
   1.565 +                  '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
   1.566 +                  '  return (-1);',
   1.567 +                  '}'
   1.568 +                  ]
   1.569 +        return TranslateList(code,
   1.570 +                             self.GetTranslation({
   1.571 +            'var' : var_name,
   1.572 +            'varlen' : var_len,
   1.573 +            'buf' : buf,
   1.574 +            'tag' : tag_name }))
   1.575 +
   1.576 +    def CodeMarshal(self, buf, tag_name, var_name, var_len):
   1.577 +        code = ['evtag_marshal(%s, %s, %s, %s);' % (
   1.578 +            buf, tag_name, var_name, var_len)]
   1.579 +        return code
   1.580 +
   1.581 +    def CodeClear(self, structname):
   1.582 +        code = [ '%s->%s_set = 0;' % (structname, self.Name()),
   1.583 +                 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
   1.584 +            structname, self._name, structname, self._name)]
   1.585 +
   1.586 +        return code
   1.587 +
   1.588 +    def CodeInitialize(self, name):
   1.589 +        code  = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
   1.590 +            name, self._name, name, self._name)]
   1.591 +        return code
   1.592 +
   1.593 +    def Verify(self):
   1.594 +        if not self._length:
   1.595 +            raise RpcGenError(
   1.596 +                'Entry "%s" needs a length '
   1.597 +                'around line %d' % (self._name, self.LineCount()))
   1.598 +
   1.599 +        Entry.Verify(self)
   1.600 +
   1.601 +class EntryInt(Entry):
   1.602 +    def __init__(self, type, name, tag, bits=32):
   1.603 +        # Init base class
   1.604 +        Entry.__init__(self, type, name, tag)
   1.605 +
   1.606 +        self._can_be_array = 1
   1.607 +        if bits == 32:
   1.608 +            self._ctype = 'ev_uint32_t'
   1.609 +            self._marshal_type = 'int'
   1.610 +        if bits == 64:
   1.611 +            self._ctype = 'ev_uint64_t'
   1.612 +            self._marshal_type = 'int64'
   1.613 +
   1.614 +    def GetInitializer(self):
   1.615 +        return "0"
   1.616 +
   1.617 +    def CodeArrayFree(self, var):
   1.618 +        return []
   1.619 +
   1.620 +    def CodeArrayAssign(self, varname, srcvar):
   1.621 +        return [ '%(varname)s = %(srcvar)s;' % { 'varname' : varname,
   1.622 +                                                'srcvar' : srcvar } ]
   1.623 +
   1.624 +    def CodeArrayAdd(self, varname, value):
   1.625 +        """Returns a new entry of this type."""
   1.626 +        return [ '%(varname)s = %(value)s;' % { 'varname' : varname,
   1.627 +                                              'value' : value } ]
   1.628 +
   1.629 +    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
   1.630 +        code = [
   1.631 +            'if (evtag_unmarshal_%(ma)s(%(buf)s, %(tag)s, &%(var)s) == -1) {',
   1.632 +            '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
   1.633 +            '  return (-1);',
   1.634 +            '}' ]
   1.635 +        code = '\n'.join(code) % self.GetTranslation({
   1.636 +            'ma'  : self._marshal_type,
   1.637 +            'buf' : buf,
   1.638 +            'tag' : tag_name,
   1.639 +            'var' : var_name })
   1.640 +        return code.split('\n')
   1.641 +
   1.642 +    def CodeMarshal(self, buf, tag_name, var_name, var_len):
   1.643 +        code = [
   1.644 +            'evtag_marshal_%s(%s, %s, %s);' % (
   1.645 +            self._marshal_type, buf, tag_name, var_name)]
   1.646 +        return code
   1.647 +
   1.648 +    def Declaration(self):
   1.649 +        dcl  = ['%s %s_data;' % (self._ctype, self._name)]
   1.650 +
   1.651 +        return dcl
   1.652 +
   1.653 +    def CodeInitialize(self, name):
   1.654 +        code = ['%s->%s_data = 0;' % (name, self._name)]
   1.655 +        return code
   1.656 +
   1.657 +class EntryString(Entry):
   1.658 +    def __init__(self, type, name, tag):
   1.659 +        # Init base class
   1.660 +        Entry.__init__(self, type, name, tag)
   1.661 +
   1.662 +        self._can_be_array = 1
   1.663 +        self._ctype = 'char *'
   1.664 +
   1.665 +    def GetInitializer(self):
   1.666 +        return "NULL"
   1.667 +
   1.668 +    def CodeArrayFree(self, varname):
   1.669 +        code = [
   1.670 +            'if (%(var)s != NULL) free(%(var)s);' ]
   1.671 +
   1.672 +        return TranslateList(code, { 'var' : varname })
   1.673 +
   1.674 +    def CodeArrayAssign(self, varname, srcvar):
   1.675 +        code = [
   1.676 +            'if (%(var)s != NULL)',
   1.677 +            '  free(%(var)s);',
   1.678 +            '%(var)s = strdup(%(srcvar)s);',
   1.679 +            'if (%(var)s == NULL) {',
   1.680 +            '  event_warnx("%%s: strdup", __func__);',
   1.681 +            '  return (-1);',
   1.682 +            '}' ]
   1.683 +
   1.684 +        return TranslateList(code, { 'var' : varname,
   1.685 +                                     'srcvar' : srcvar })
   1.686 +
   1.687 +    def CodeArrayAdd(self, varname, value):
   1.688 +        code = [
   1.689 +            'if (%(value)s != NULL) {',
   1.690 +            '  %(var)s = strdup(%(value)s);',
   1.691 +            '  if (%(var)s == NULL) {',
   1.692 +            '    goto error;',
   1.693 +            '  }',
   1.694 +            '} else {',
   1.695 +            '  %(var)s = NULL;',
   1.696 +            '}' ]
   1.697 +
   1.698 +        return TranslateList(code, { 'var' : varname,
   1.699 +                                     'value' : value })
   1.700 +
   1.701 +    def GetVarLen(self, var):
   1.702 +        return 'strlen(%s)' % self.GetVarName(var)
   1.703 +
   1.704 +    def CodeMakeInitalize(self, varname):
   1.705 +        return '%(varname)s = NULL;' % { 'varname' : varname }
   1.706 +
   1.707 +    def CodeAssign(self):
   1.708 +        name = self._name
   1.709 +        code = """int
   1.710 +%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
   1.711 +    const %(ctype)s value)
   1.712 +{
   1.713 +  if (msg->%(name)s_data != NULL)
   1.714 +    free(msg->%(name)s_data);
   1.715 +  if ((msg->%(name)s_data = strdup(value)) == NULL)
   1.716 +    return (-1);
   1.717 +  msg->%(name)s_set = 1;
   1.718 +  return (0);
   1.719 +}""" % self.GetTranslation()
   1.720 +
   1.721 +        return code.split('\n')
   1.722 +
   1.723 +    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
   1.724 +        code = ['if (evtag_unmarshal_string(%(buf)s, %(tag)s, &%(var)s) == -1) {',
   1.725 +                '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
   1.726 +                '  return (-1);',
   1.727 +                '}'
   1.728 +                ]
   1.729 +        code = '\n'.join(code) % self.GetTranslation({
   1.730 +            'buf' : buf,
   1.731 +            'tag' : tag_name,
   1.732 +            'var' : var_name })
   1.733 +        return code.split('\n')
   1.734 +
   1.735 +    def CodeMarshal(self, buf, tag_name, var_name, var_len):
   1.736 +        code = ['evtag_marshal_string(%s, %s, %s);' % (
   1.737 +            buf, tag_name, var_name)]
   1.738 +        return code
   1.739 +
   1.740 +    def CodeClear(self, structname):
   1.741 +        code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
   1.742 +                 '  free(%s->%s_data);' % (structname, self.Name()),
   1.743 +                 '  %s->%s_data = NULL;' % (structname, self.Name()),
   1.744 +                 '  %s->%s_set = 0;' % (structname, self.Name()),
   1.745 +                 '}'
   1.746 +                 ]
   1.747 +
   1.748 +        return code
   1.749 +
   1.750 +    def CodeInitialize(self, name):
   1.751 +        code  = ['%s->%s_data = NULL;' % (name, self._name)]
   1.752 +        return code
   1.753 +
   1.754 +    def CodeFree(self, name):
   1.755 +        code  = ['if (%s->%s_data != NULL)' % (name, self._name),
   1.756 +                 '    free (%s->%s_data);' % (name, self._name)]
   1.757 +
   1.758 +        return code
   1.759 +
   1.760 +    def Declaration(self):
   1.761 +        dcl  = ['char *%s_data;' % self._name]
   1.762 +
   1.763 +        return dcl
   1.764 +
   1.765 +class EntryStruct(Entry):
   1.766 +    def __init__(self, type, name, tag, refname):
   1.767 +        # Init base class
   1.768 +        Entry.__init__(self, type, name, tag)
   1.769 +
   1.770 +        self._optpointer = False
   1.771 +        self._can_be_array = 1
   1.772 +        self._refname = refname
   1.773 +        self._ctype = 'struct %s*' % refname
   1.774 +        self._optaddarg = False
   1.775 +
   1.776 +    def GetInitializer(self):
   1.777 +        return "NULL"
   1.778 +
   1.779 +    def GetVarLen(self, var):
   1.780 +        return '-1'
   1.781 +
   1.782 +    def CodeArrayAdd(self, varname, value):
   1.783 +        code = [
   1.784 +            '%(varname)s = %(refname)s_new();',
   1.785 +            'if (%(varname)s == NULL)',
   1.786 +            '  goto error;' ]
   1.787 +
   1.788 +        return TranslateList(code, self.GetTranslation({ 'varname' : varname }))
   1.789 +
   1.790 +    def CodeArrayFree(self, var):
   1.791 +        code = [ '%(refname)s_free(%(var)s);' % self.GetTranslation(
   1.792 +            { 'var' : var }) ]
   1.793 +        return code
   1.794 +
   1.795 +    def CodeArrayAssign(self, var, srcvar):
   1.796 +        code = [
   1.797 +            'int had_error = 0;',
   1.798 +            'struct evbuffer *tmp = NULL;',
   1.799 +            '%(refname)s_clear(%(var)s);',
   1.800 +            'if ((tmp = evbuffer_new()) == NULL) {',
   1.801 +            '  event_warn("%%s: evbuffer_new()", __func__);',
   1.802 +            '  had_error = 1;',
   1.803 +            '  goto done;',
   1.804 +            '}',
   1.805 +            '%(refname)s_marshal(tmp, %(srcvar)s);',
   1.806 +            'if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {',
   1.807 +            '  event_warnx("%%s: %(refname)s_unmarshal", __func__);',
   1.808 +            '  had_error = 1;',
   1.809 +            '  goto done;',
   1.810 +            '}',
   1.811 +            'done:'
   1.812 +            'if (tmp != NULL)',
   1.813 +            '  evbuffer_free(tmp);',
   1.814 +            'if (had_error) {',
   1.815 +            '  %(refname)s_clear(%(var)s);',
   1.816 +            '  return (-1);',
   1.817 +            '}' ]
   1.818 +
   1.819 +        return TranslateList(code, self.GetTranslation({
   1.820 +            'var' : var,
   1.821 +            'srcvar' : srcvar}))
   1.822 +
   1.823 +    def CodeGet(self):
   1.824 +        name = self._name
   1.825 +        code = [ 'int',
   1.826 +                 '%s_%s_get(struct %s *msg, %s *value)' % (
   1.827 +            self._struct.Name(), name,
   1.828 +            self._struct.Name(), self._ctype),
   1.829 +                 '{',
   1.830 +                 '  if (msg->%s_set != 1) {' % name,
   1.831 +                 '    msg->%s_data = %s_new();' % (name, self._refname),
   1.832 +                 '    if (msg->%s_data == NULL)' % name,
   1.833 +                 '      return (-1);',
   1.834 +                 '    msg->%s_set = 1;' % name,
   1.835 +                 '  }',
   1.836 +                 '  *value = msg->%s_data;' % name,
   1.837 +                 '  return (0);',
   1.838 +                 '}' ]
   1.839 +        return code
   1.840 +
   1.841 +    def CodeAssign(self):
   1.842 +        name = self._name
   1.843 +        code = """int
   1.844 +%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
   1.845 +    const %(ctype)s value)
   1.846 +{
   1.847 +   struct evbuffer *tmp = NULL;
   1.848 +   if (msg->%(name)s_set) {
   1.849 +     %(refname)s_clear(msg->%(name)s_data);
   1.850 +     msg->%(name)s_set = 0;
   1.851 +   } else {
   1.852 +     msg->%(name)s_data = %(refname)s_new();
   1.853 +     if (msg->%(name)s_data == NULL) {
   1.854 +       event_warn("%%s: %(refname)s_new()", __func__);
   1.855 +       goto error;
   1.856 +     }
   1.857 +   }
   1.858 +   if ((tmp = evbuffer_new()) == NULL) {
   1.859 +     event_warn("%%s: evbuffer_new()", __func__);
   1.860 +     goto error;
   1.861 +   }
   1.862 +   %(refname)s_marshal(tmp, value);
   1.863 +   if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) {
   1.864 +     event_warnx("%%s: %(refname)s_unmarshal", __func__);
   1.865 +     goto error;
   1.866 +   }
   1.867 +   msg->%(name)s_set = 1;
   1.868 +   evbuffer_free(tmp);
   1.869 +   return (0);
   1.870 + error:
   1.871 +   if (tmp != NULL)
   1.872 +     evbuffer_free(tmp);
   1.873 +   if (msg->%(name)s_data != NULL) {
   1.874 +     %(refname)s_free(msg->%(name)s_data);
   1.875 +     msg->%(name)s_data = NULL;
   1.876 +   }
   1.877 +   return (-1);
   1.878 +}""" % self.GetTranslation()
   1.879 +        return code.split('\n')
   1.880 +
   1.881 +    def CodeComplete(self, structname, var_name):
   1.882 +        code = [ 'if (%(structname)s->%(name)s_set && '
   1.883 +                 '%(refname)s_complete(%(var)s) == -1)',
   1.884 +                 '  return (-1);' ]
   1.885 +
   1.886 +        return TranslateList(code, self.GetTranslation({
   1.887 +            'structname' : structname,
   1.888 +            'var' : var_name }))
   1.889 +
   1.890 +    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
   1.891 +        code = ['%(var)s = %(refname)s_new();',
   1.892 +                'if (%(var)s == NULL)',
   1.893 +                '  return (-1);',
   1.894 +                'if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag)s, '
   1.895 +                '%(var)s) == -1) {',
   1.896 +                  '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
   1.897 +                '  return (-1);',
   1.898 +                '}'
   1.899 +                ]
   1.900 +        code = '\n'.join(code) % self.GetTranslation({
   1.901 +            'buf' : buf,
   1.902 +            'tag' : tag_name,
   1.903 +            'var' : var_name })
   1.904 +        return code.split('\n')
   1.905 +
   1.906 +    def CodeMarshal(self, buf, tag_name, var_name, var_len):
   1.907 +        code = ['evtag_marshal_%s(%s, %s, %s);' % (
   1.908 +            self._refname, buf, tag_name, var_name)]
   1.909 +        return code
   1.910 +
   1.911 +    def CodeClear(self, structname):
   1.912 +        code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
   1.913 +                 '  %s_free(%s->%s_data);' % (
   1.914 +            self._refname, structname, self.Name()),
   1.915 +                 '  %s->%s_data = NULL;' % (structname, self.Name()),
   1.916 +                 '  %s->%s_set = 0;' % (structname, self.Name()),
   1.917 +                 '}'
   1.918 +                 ]
   1.919 +
   1.920 +        return code
   1.921 +
   1.922 +    def CodeInitialize(self, name):
   1.923 +        code  = ['%s->%s_data = NULL;' % (name, self._name)]
   1.924 +        return code
   1.925 +
   1.926 +    def CodeFree(self, name):
   1.927 +        code  = ['if (%s->%s_data != NULL)' % (name, self._name),
   1.928 +                 '    %s_free(%s->%s_data);' % (
   1.929 +            self._refname, name, self._name)]
   1.930 +
   1.931 +        return code
   1.932 +
   1.933 +    def Declaration(self):
   1.934 +        dcl  = ['%s %s_data;' % (self._ctype, self._name)]
   1.935 +
   1.936 +        return dcl
   1.937 +
   1.938 +class EntryVarBytes(Entry):
   1.939 +    def __init__(self, type, name, tag):
   1.940 +        # Init base class
   1.941 +        Entry.__init__(self, type, name, tag)
   1.942 +
   1.943 +        self._ctype = 'ev_uint8_t *'
   1.944 +
   1.945 +    def GetInitializer(self):
   1.946 +        return "NULL"
   1.947 +
   1.948 +    def GetVarLen(self, var):
   1.949 +        return '%(var)s->%(name)s_length' % self.GetTranslation({ 'var' : var })
   1.950 +
   1.951 +    def CodeArrayAdd(self, varname, value):
   1.952 +        # xxx: copy
   1.953 +        return [ '%(varname)s = NULL;' % { 'varname' : varname } ]
   1.954 +
   1.955 +    def GetDeclaration(self, funcname):
   1.956 +        code = [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % (
   1.957 +            funcname, self._struct.Name(), self._ctype ) ]
   1.958 +        return code
   1.959 +
   1.960 +    def AssignDeclaration(self, funcname):
   1.961 +        code = [ 'int %s(struct %s *, const %s, ev_uint32_t);' % (
   1.962 +            funcname, self._struct.Name(), self._ctype ) ]
   1.963 +        return code
   1.964 +
   1.965 +    def CodeAssign(self):
   1.966 +        name = self._name
   1.967 +        code = [ 'int',
   1.968 +                 '%s_%s_assign(struct %s *msg, '
   1.969 +                 'const %s value, ev_uint32_t len)' % (
   1.970 +            self._struct.Name(), name,
   1.971 +            self._struct.Name(), self._ctype),
   1.972 +                 '{',
   1.973 +                 '  if (msg->%s_data != NULL)' % name,
   1.974 +                 '    free (msg->%s_data);' % name,
   1.975 +                 '  msg->%s_data = malloc(len);' % name,
   1.976 +                 '  if (msg->%s_data == NULL)' % name,
   1.977 +                 '    return (-1);',
   1.978 +                 '  msg->%s_set = 1;' % name,
   1.979 +                 '  msg->%s_length = len;' % name,
   1.980 +                 '  memcpy(msg->%s_data, value, len);' % name,
   1.981 +                 '  return (0);',
   1.982 +                 '}' ]
   1.983 +        return code
   1.984 +
   1.985 +    def CodeGet(self):
   1.986 +        name = self._name
   1.987 +        code = [ 'int',
   1.988 +                 '%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)' % (
   1.989 +            self._struct.Name(), name,
   1.990 +            self._struct.Name(), self._ctype),
   1.991 +                 '{',
   1.992 +                 '  if (msg->%s_set != 1)' % name,
   1.993 +                 '    return (-1);',
   1.994 +                 '  *value = msg->%s_data;' % name,
   1.995 +                 '  *plen = msg->%s_length;' % name,
   1.996 +                 '  return (0);',
   1.997 +                 '}' ]
   1.998 +        return code
   1.999 +
  1.1000 +    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
  1.1001 +        code = ['if (evtag_payload_length(%(buf)s, &%(varlen)s) == -1)',
  1.1002 +                '  return (-1);',
  1.1003 +                # We do not want DoS opportunities
  1.1004 +                'if (%(varlen)s > evbuffer_get_length(%(buf)s))',
  1.1005 +                '  return (-1);',
  1.1006 +                'if ((%(var)s = malloc(%(varlen)s)) == NULL)',
  1.1007 +                '  return (-1);',
  1.1008 +                'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, %(var)s, '
  1.1009 +                '%(varlen)s) == -1) {',
  1.1010 +                '  event_warnx("%%s: failed to unmarshal %(name)s", __func__);',
  1.1011 +                '  return (-1);',
  1.1012 +                '}'
  1.1013 +                ]
  1.1014 +        code = '\n'.join(code) % self.GetTranslation({
  1.1015 +            'buf' : buf,
  1.1016 +            'tag' : tag_name,
  1.1017 +            'var' : var_name,
  1.1018 +            'varlen' : var_len })
  1.1019 +        return code.split('\n')
  1.1020 +
  1.1021 +    def CodeMarshal(self, buf, tag_name, var_name, var_len):
  1.1022 +        code = ['evtag_marshal(%s, %s, %s, %s);' % (
  1.1023 +            buf, tag_name, var_name, var_len)]
  1.1024 +        return code
  1.1025 +
  1.1026 +    def CodeClear(self, structname):
  1.1027 +        code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
  1.1028 +                 '  free (%s->%s_data);' % (structname, self.Name()),
  1.1029 +                 '  %s->%s_data = NULL;' % (structname, self.Name()),
  1.1030 +                 '  %s->%s_length = 0;' % (structname, self.Name()),
  1.1031 +                 '  %s->%s_set = 0;' % (structname, self.Name()),
  1.1032 +                 '}'
  1.1033 +                 ]
  1.1034 +
  1.1035 +        return code
  1.1036 +
  1.1037 +    def CodeInitialize(self, name):
  1.1038 +        code  = ['%s->%s_data = NULL;' % (name, self._name),
  1.1039 +                 '%s->%s_length = 0;' % (name, self._name) ]
  1.1040 +        return code
  1.1041 +
  1.1042 +    def CodeFree(self, name):
  1.1043 +        code  = ['if (%s->%s_data != NULL)' % (name, self._name),
  1.1044 +                 '    free(%s->%s_data);' % (name, self._name)]
  1.1045 +
  1.1046 +        return code
  1.1047 +
  1.1048 +    def Declaration(self):
  1.1049 +        dcl  = ['ev_uint8_t *%s_data;' % self._name,
  1.1050 +                'ev_uint32_t %s_length;' % self._name]
  1.1051 +
  1.1052 +        return dcl
  1.1053 +
  1.1054 +class EntryArray(Entry):
  1.1055 +    def __init__(self, entry):
  1.1056 +        # Init base class
  1.1057 +        Entry.__init__(self, entry._type, entry._name, entry._tag)
  1.1058 +
  1.1059 +        self._entry = entry
  1.1060 +        self._refname = entry._refname
  1.1061 +        self._ctype = self._entry._ctype
  1.1062 +        self._optional = True
  1.1063 +        self._optpointer = self._entry._optpointer
  1.1064 +        self._optaddarg = self._entry._optaddarg
  1.1065 +
  1.1066 +        # provide a new function for accessing the variable name
  1.1067 +        def GetVarName(var_name):
  1.1068 +            return '%(var)s->%(name)s_data[%(index)s]' % \
  1.1069 +                   self._entry.GetTranslation({'var' : var_name,
  1.1070 +                                               'index' : self._index})
  1.1071 +        self._entry.GetVarName = GetVarName
  1.1072 +
  1.1073 +    def GetInitializer(self):
  1.1074 +        return "NULL"
  1.1075 +
  1.1076 +    def GetVarName(self, var_name):
  1.1077 +        return var_name
  1.1078 +
  1.1079 +    def GetVarLen(self, var_name):
  1.1080 +        return '-1'
  1.1081 +
  1.1082 +    def GetDeclaration(self, funcname):
  1.1083 +        """Allows direct access to elements of the array."""
  1.1084 +        code = [
  1.1085 +            'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' %
  1.1086 +            self.GetTranslation({ 'funcname' : funcname }) ]
  1.1087 +        return code
  1.1088 +
  1.1089 +    def AssignDeclaration(self, funcname):
  1.1090 +        code = [ 'int %s(struct %s *, int, const %s);' % (
  1.1091 +            funcname, self._struct.Name(), self._ctype ) ]
  1.1092 +        return code
  1.1093 +
  1.1094 +    def AddDeclaration(self, funcname):
  1.1095 +        code = [
  1.1096 +            '%(ctype)s %(optpointer)s '
  1.1097 +            '%(funcname)s(struct %(parent_name)s *msg%(optaddarg)s);' % \
  1.1098 +            self.GetTranslation({ 'funcname' : funcname }) ]
  1.1099 +        return code
  1.1100 +
  1.1101 +    def CodeGet(self):
  1.1102 +        code = """int
  1.1103 +%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset,
  1.1104 +    %(ctype)s *value)
  1.1105 +{
  1.1106 +  if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length)
  1.1107 +    return (-1);
  1.1108 +  *value = msg->%(name)s_data[offset];
  1.1109 +  return (0);
  1.1110 +}""" % self.GetTranslation()
  1.1111 +
  1.1112 +        return code.split('\n')
  1.1113 +
  1.1114 +    def CodeAssign(self):
  1.1115 +        code = [
  1.1116 +            'int',
  1.1117 +            '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,',
  1.1118 +            '    const %(ctype)s value)',
  1.1119 +            '{',
  1.1120 +            '  if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)',
  1.1121 +            '    return (-1);\n',
  1.1122 +            '  {' ]
  1.1123 +        code = TranslateList(code, self.GetTranslation())
  1.1124 +
  1.1125 +        codearrayassign = self._entry.CodeArrayAssign(
  1.1126 +            'msg->%(name)s_data[off]' % self.GetTranslation(), 'value')
  1.1127 +        code += map(lambda x: '    ' + x, codearrayassign)
  1.1128 +
  1.1129 +        code += TranslateList([
  1.1130 +            '  }',
  1.1131 +            '  return (0);',
  1.1132 +            '}' ], self.GetTranslation())
  1.1133 +
  1.1134 +        return code
  1.1135 +
  1.1136 +    def CodeAdd(self):
  1.1137 +        codearrayadd = self._entry.CodeArrayAdd(
  1.1138 +            'msg->%(name)s_data[msg->%(name)s_length - 1]' % self.GetTranslation(),
  1.1139 +            'value')
  1.1140 +        code = [
  1.1141 +            'static int',
  1.1142 +            '%(parent_name)s_%(name)s_expand_to_hold_more('
  1.1143 +            'struct %(parent_name)s *msg)',
  1.1144 +            '{',
  1.1145 +            '  int tobe_allocated = msg->%(name)s_num_allocated;',
  1.1146 +            '  %(ctype)s* new_data = NULL;',
  1.1147 +            '  tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;',
  1.1148 +            '  new_data = (%(ctype)s*) realloc(msg->%(name)s_data,',
  1.1149 +            '      tobe_allocated * sizeof(%(ctype)s));',
  1.1150 +            '  if (new_data == NULL)',
  1.1151 +            '    return -1;',
  1.1152 +            '  msg->%(name)s_data = new_data;',
  1.1153 +            '  msg->%(name)s_num_allocated = tobe_allocated;',
  1.1154 +            '  return 0;'
  1.1155 +            '}',
  1.1156 +            '',
  1.1157 +            '%(ctype)s %(optpointer)s',
  1.1158 +            '%(parent_name)s_%(name)s_add('
  1.1159 +            'struct %(parent_name)s *msg%(optaddarg)s)',
  1.1160 +            '{',
  1.1161 +            '  if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {',
  1.1162 +            '    if (%(parent_name)s_%(name)s_expand_to_hold_more(msg)<0)',
  1.1163 +            '      goto error;',
  1.1164 +            '  }' ]
  1.1165 +
  1.1166 +        code = TranslateList(code, self.GetTranslation())
  1.1167 +
  1.1168 +        code += map(lambda x: '  ' + x, codearrayadd)
  1.1169 +
  1.1170 +        code += TranslateList([
  1.1171 +            '  msg->%(name)s_set = 1;',
  1.1172 +            '  return %(optreference)s(msg->%(name)s_data['
  1.1173 +            'msg->%(name)s_length - 1]);',
  1.1174 +            'error:',
  1.1175 +            '  --msg->%(name)s_length;',
  1.1176 +            '  return (NULL);',
  1.1177 +            '}' ], self.GetTranslation())
  1.1178 +
  1.1179 +        return code
  1.1180 +
  1.1181 +    def CodeComplete(self, structname, var_name):
  1.1182 +        self._index = 'i'
  1.1183 +        tmp = self._entry.CodeComplete(structname, self._entry.GetVarName(var_name))
  1.1184 +        # skip the whole loop if there is nothing to check
  1.1185 +        if not tmp:
  1.1186 +            return []
  1.1187 +
  1.1188 +        translate = self.GetTranslation({ 'structname' : structname })
  1.1189 +        code = [
  1.1190 +            '{',
  1.1191 +            '  int i;',
  1.1192 +            '  for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ]
  1.1193 +
  1.1194 +        code = TranslateList(code, translate)
  1.1195 +
  1.1196 +        code += map(lambda x: '    ' + x, tmp)
  1.1197 +
  1.1198 +        code += [
  1.1199 +            '  }',
  1.1200 +            '}' ]
  1.1201 +
  1.1202 +        return code
  1.1203 +
  1.1204 +    def CodeUnmarshal(self, buf, tag_name, var_name, var_len):
  1.1205 +        translate = self.GetTranslation({ 'var' : var_name,
  1.1206 +                                          'buf' : buf,
  1.1207 +                                          'tag' : tag_name,
  1.1208 +                                          'init' : self._entry.GetInitializer()})
  1.1209 +        code = [
  1.1210 +            'if (%(var)s->%(name)s_length >= %(var)s->%(name)s_num_allocated &&',
  1.1211 +            '    %(parent_name)s_%(name)s_expand_to_hold_more(%(var)s) < 0) {',
  1.1212 +            '  puts("HEY NOW");',
  1.1213 +            '  return (-1);',
  1.1214 +            '}']
  1.1215 +
  1.1216 +        # the unmarshal code directly returns
  1.1217 +        code = TranslateList(code, translate)
  1.1218 +
  1.1219 +        self._index = '%(var)s->%(name)s_length' % translate
  1.1220 +        code += self._entry.CodeUnmarshal(buf, tag_name,
  1.1221 +                                        self._entry.GetVarName(var_name),
  1.1222 +                                        self._entry.GetVarLen(var_name))
  1.1223 +
  1.1224 +        code += [ '++%(var)s->%(name)s_length;' % translate ]
  1.1225 +
  1.1226 +        return code
  1.1227 +
  1.1228 +    def CodeMarshal(self, buf, tag_name, var_name, var_len):
  1.1229 +        code = ['{',
  1.1230 +                '  int i;',
  1.1231 +                '  for (i = 0; i < %(var)s->%(name)s_length; ++i) {' ]
  1.1232 +
  1.1233 +        self._index = 'i'
  1.1234 +        code += self._entry.CodeMarshal(buf, tag_name,
  1.1235 +                                        self._entry.GetVarName(var_name),
  1.1236 +                                        self._entry.GetVarLen(var_name))
  1.1237 +        code += ['  }',
  1.1238 +                 '}'
  1.1239 +                 ]
  1.1240 +
  1.1241 +        code = "\n".join(code) % self.GetTranslation({ 'var' : var_name })
  1.1242 +
  1.1243 +        return code.split('\n')
  1.1244 +
  1.1245 +    def CodeClear(self, structname):
  1.1246 +        translate = self.GetTranslation({ 'structname' : structname })
  1.1247 +        codearrayfree = self._entry.CodeArrayFree(
  1.1248 +            '%(structname)s->%(name)s_data[i]' % self.GetTranslation(
  1.1249 +            { 'structname' : structname } ))
  1.1250 +
  1.1251 +        code = [ 'if (%(structname)s->%(name)s_set == 1) {' ]
  1.1252 +
  1.1253 +        if codearrayfree:
  1.1254 +            code += [
  1.1255 +                '  int i;',
  1.1256 +                '  for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ]
  1.1257 +
  1.1258 +        code = TranslateList(code, translate)
  1.1259 +
  1.1260 +        if codearrayfree:
  1.1261 +            code += map(lambda x: '    ' + x, codearrayfree)
  1.1262 +            code += [
  1.1263 +                '  }' ]
  1.1264 +
  1.1265 +        code += TranslateList([
  1.1266 +                 '  free(%(structname)s->%(name)s_data);',
  1.1267 +                 '  %(structname)s->%(name)s_data = NULL;',
  1.1268 +                 '  %(structname)s->%(name)s_set = 0;',
  1.1269 +                 '  %(structname)s->%(name)s_length = 0;',
  1.1270 +                 '  %(structname)s->%(name)s_num_allocated = 0;',
  1.1271 +                 '}'
  1.1272 +                 ], translate)
  1.1273 +
  1.1274 +        return code
  1.1275 +
  1.1276 +    def CodeInitialize(self, name):
  1.1277 +        code  = ['%s->%s_data = NULL;' % (name, self._name),
  1.1278 +                 '%s->%s_length = 0;' % (name, self._name),
  1.1279 +                 '%s->%s_num_allocated = 0;' % (name, self._name)]
  1.1280 +        return code
  1.1281 +
  1.1282 +    def CodeFree(self, structname):
  1.1283 +        code = self.CodeClear(structname);
  1.1284 +
  1.1285 +        code += TranslateList([
  1.1286 +            'free(%(structname)s->%(name)s_data);' ],
  1.1287 +                              self.GetTranslation({'structname' : structname }))
  1.1288 +
  1.1289 +        return code
  1.1290 +
  1.1291 +    def Declaration(self):
  1.1292 +        dcl  = ['%s *%s_data;' % (self._ctype, self._name),
  1.1293 +                'int %s_length;' % self._name,
  1.1294 +                'int %s_num_allocated;' % self._name ]
  1.1295 +
  1.1296 +        return dcl
  1.1297 +
  1.1298 +def NormalizeLine(line):
  1.1299 +    global white
  1.1300 +    global cppcomment
  1.1301 +
  1.1302 +    line = cppcomment.sub('', line)
  1.1303 +    line = line.strip()
  1.1304 +    line = white.sub(' ', line)
  1.1305 +
  1.1306 +    return line
  1.1307 +
  1.1308 +def ProcessOneEntry(factory, newstruct, entry):
  1.1309 +    optional = 0
  1.1310 +    array = 0
  1.1311 +    entry_type = ''
  1.1312 +    name = ''
  1.1313 +    tag = ''
  1.1314 +    tag_set = None
  1.1315 +    separator = ''
  1.1316 +    fixed_length = ''
  1.1317 +
  1.1318 +    tokens = entry.split(' ')
  1.1319 +    while tokens:
  1.1320 +        token = tokens[0]
  1.1321 +        tokens = tokens[1:]
  1.1322 +
  1.1323 +        if not entry_type:
  1.1324 +            if not optional and token == 'optional':
  1.1325 +                optional = 1
  1.1326 +                continue
  1.1327 +
  1.1328 +            if not array and token == 'array':
  1.1329 +                array = 1
  1.1330 +                continue
  1.1331 +
  1.1332 +        if not entry_type:
  1.1333 +            entry_type = token
  1.1334 +            continue
  1.1335 +
  1.1336 +        if not name:
  1.1337 +            res = re.match(r'^([^\[\]]+)(\[.*\])?$', token)
  1.1338 +            if not res:
  1.1339 +                 raise RpcGenError(
  1.1340 +                     'Cannot parse name: \"%s\" '
  1.1341 +                     'around line %d' % (entry, line_count))
  1.1342 +            name = res.group(1)
  1.1343 +            fixed_length = res.group(2)
  1.1344 +            if fixed_length:
  1.1345 +                fixed_length = fixed_length[1:-1]
  1.1346 +            continue
  1.1347 +
  1.1348 +        if not separator:
  1.1349 +            separator = token
  1.1350 +            if separator != '=':
  1.1351 +                 raise RpcGenError('Expected "=" after name \"%s\" got %s'
  1.1352 +                                   % (name, token))
  1.1353 +            continue
  1.1354 +
  1.1355 +        if not tag_set:
  1.1356 +            tag_set = 1
  1.1357 +            if not re.match(r'^(0x)?[0-9]+$', token):
  1.1358 +                raise RpcGenError('Expected tag number: \"%s\"' % entry)
  1.1359 +            tag = int(token, 0)
  1.1360 +            continue
  1.1361 +
  1.1362 +        raise RpcGenError('Cannot parse \"%s\"' % entry)
  1.1363 +
  1.1364 +    if not tag_set:
  1.1365 +        raise RpcGenError('Need tag number: \"%s\"' % entry)
  1.1366 +
  1.1367 +    # Create the right entry
  1.1368 +    if entry_type == 'bytes':
  1.1369 +        if fixed_length:
  1.1370 +            newentry = factory.EntryBytes(entry_type, name, tag, fixed_length)
  1.1371 +        else:
  1.1372 +            newentry = factory.EntryVarBytes(entry_type, name, tag)
  1.1373 +    elif entry_type == 'int' and not fixed_length:
  1.1374 +        newentry = factory.EntryInt(entry_type, name, tag)
  1.1375 +    elif entry_type == 'int64' and not fixed_length:
  1.1376 +        newentry = factory.EntryInt(entry_type, name, tag, bits=64)
  1.1377 +    elif entry_type == 'string' and not fixed_length:
  1.1378 +        newentry = factory.EntryString(entry_type, name, tag)
  1.1379 +    else:
  1.1380 +        res = structref.match(entry_type)
  1.1381 +        if res:
  1.1382 +            # References another struct defined in our file
  1.1383 +            newentry = factory.EntryStruct(entry_type, name, tag, res.group(1))
  1.1384 +        else:
  1.1385 +            raise RpcGenError('Bad type: "%s" in "%s"' % (entry_type, entry))
  1.1386 +
  1.1387 +    structs = []
  1.1388 +
  1.1389 +    if optional:
  1.1390 +        newentry.MakeOptional()
  1.1391 +    if array:
  1.1392 +        newentry.MakeArray()
  1.1393 +
  1.1394 +    newentry.SetStruct(newstruct)
  1.1395 +    newentry.SetLineCount(line_count)
  1.1396 +    newentry.Verify()
  1.1397 +
  1.1398 +    if array:
  1.1399 +        # We need to encapsulate this entry into a struct
  1.1400 +        newname = newentry.Name()+ '_array'
  1.1401 +
  1.1402 +        # Now borgify the new entry.
  1.1403 +        newentry = factory.EntryArray(newentry)
  1.1404 +        newentry.SetStruct(newstruct)
  1.1405 +        newentry.SetLineCount(line_count)
  1.1406 +        newentry.MakeArray()
  1.1407 +
  1.1408 +    newstruct.AddEntry(newentry)
  1.1409 +
  1.1410 +    return structs
  1.1411 +
  1.1412 +def ProcessStruct(factory, data):
  1.1413 +    tokens = data.split(' ')
  1.1414 +
  1.1415 +    # First three tokens are: 'struct' 'name' '{'
  1.1416 +    newstruct = factory.Struct(tokens[1])
  1.1417 +
  1.1418 +    inside = ' '.join(tokens[3:-1])
  1.1419 +
  1.1420 +    tokens = inside.split(';')
  1.1421 +
  1.1422 +    structs = []
  1.1423 +
  1.1424 +    for entry in tokens:
  1.1425 +        entry = NormalizeLine(entry)
  1.1426 +        if not entry:
  1.1427 +            continue
  1.1428 +
  1.1429 +        # It's possible that new structs get defined in here
  1.1430 +        structs.extend(ProcessOneEntry(factory, newstruct, entry))
  1.1431 +
  1.1432 +    structs.append(newstruct)
  1.1433 +    return structs
  1.1434 +
  1.1435 +def GetNextStruct(file):
  1.1436 +    global line_count
  1.1437 +    global cppdirect
  1.1438 +
  1.1439 +    got_struct = 0
  1.1440 +
  1.1441 +    processed_lines = []
  1.1442 +
  1.1443 +    have_c_comment = 0
  1.1444 +    data = ''
  1.1445 +    while 1:
  1.1446 +        line = file.readline()
  1.1447 +        if not line:
  1.1448 +            break
  1.1449 +
  1.1450 +        line_count += 1
  1.1451 +        line = line[:-1]
  1.1452 +
  1.1453 +        if not have_c_comment and re.search(r'/\*', line):
  1.1454 +            if re.search(r'/\*.*?\*/', line):
  1.1455 +                line = re.sub(r'/\*.*?\*/', '', line)
  1.1456 +            else:
  1.1457 +                line = re.sub(r'/\*.*$', '', line)
  1.1458 +                have_c_comment = 1
  1.1459 +
  1.1460 +        if have_c_comment:
  1.1461 +            if not re.search(r'\*/', line):
  1.1462 +                continue
  1.1463 +            have_c_comment = 0
  1.1464 +            line = re.sub(r'^.*\*/', '', line)
  1.1465 +
  1.1466 +        line = NormalizeLine(line)
  1.1467 +
  1.1468 +        if not line:
  1.1469 +            continue
  1.1470 +
  1.1471 +        if not got_struct:
  1.1472 +            if re.match(r'#include ["<].*[>"]', line):
  1.1473 +                cppdirect.append(line)
  1.1474 +                continue
  1.1475 +
  1.1476 +            if re.match(r'^#(if( |def)|endif)', line):
  1.1477 +                cppdirect.append(line)
  1.1478 +                continue
  1.1479 +
  1.1480 +            if re.match(r'^#define', line):
  1.1481 +                headerdirect.append(line)
  1.1482 +                continue
  1.1483 +
  1.1484 +            if not structdef.match(line):
  1.1485 +                raise RpcGenError('Missing struct on line %d: %s'
  1.1486 +                                  % (line_count, line))
  1.1487 +            else:
  1.1488 +                got_struct = 1
  1.1489 +                data += line
  1.1490 +            continue
  1.1491 +
  1.1492 +        # We are inside the struct
  1.1493 +        tokens = line.split('}')
  1.1494 +        if len(tokens) == 1:
  1.1495 +            data += ' ' + line
  1.1496 +            continue
  1.1497 +
  1.1498 +        if len(tokens[1]):
  1.1499 +            raise RpcGenError('Trailing garbage after struct on line %d'
  1.1500 +                              % line_count)
  1.1501 +
  1.1502 +        # We found the end of the struct
  1.1503 +        data += ' %s}' % tokens[0]
  1.1504 +        break
  1.1505 +
  1.1506 +    # Remove any comments, that might be in there
  1.1507 +    data = re.sub(r'/\*.*\*/', '', data)
  1.1508 +
  1.1509 +    return data
  1.1510 +
  1.1511 +
  1.1512 +def Parse(factory, file):
  1.1513 +    """
  1.1514 +    Parses the input file and returns C code and corresponding header file.
  1.1515 +    """
  1.1516 +
  1.1517 +    entities = []
  1.1518 +
  1.1519 +    while 1:
  1.1520 +        # Just gets the whole struct nicely formatted
  1.1521 +        data = GetNextStruct(file)
  1.1522 +
  1.1523 +        if not data:
  1.1524 +            break
  1.1525 +
  1.1526 +        entities.extend(ProcessStruct(factory, data))
  1.1527 +
  1.1528 +    return entities
  1.1529 +
  1.1530 +class CCodeGenerator:
  1.1531 +    def __init__(self):
  1.1532 +        pass
  1.1533 +
  1.1534 +    def GuardName(self, name):
  1.1535 +        # Use the complete provided path to the input file, with all
  1.1536 +        # non-identifier characters replaced with underscores, to
  1.1537 +        # reduce the chance of a collision between guard macros.
  1.1538 +        return '_' + nonident.sub('_', name).upper() + '_'
  1.1539 +
  1.1540 +    def HeaderPreamble(self, name):
  1.1541 +        guard = self.GuardName(name)
  1.1542 +        pre = (
  1.1543 +            '/*\n'
  1.1544 +            ' * Automatically generated from %s\n'
  1.1545 +            ' */\n\n'
  1.1546 +            '#ifndef %s\n'
  1.1547 +            '#define %s\n\n' ) % (
  1.1548 +            name, guard, guard)
  1.1549 +
  1.1550 +        for statement in headerdirect:
  1.1551 +            pre += '%s\n' % statement
  1.1552 +        if headerdirect:
  1.1553 +            pre += '\n'
  1.1554 +
  1.1555 +        pre += (
  1.1556 +            '#include <event2/util.h> /* for ev_uint*_t */\n'
  1.1557 +            '#include <event2/rpc.h>\n'
  1.1558 +        )
  1.1559 +
  1.1560 +        return pre
  1.1561 +
  1.1562 +    def HeaderPostamble(self, name):
  1.1563 +        guard = self.GuardName(name)
  1.1564 +        return '#endif  /* %s */' % guard
  1.1565 +
  1.1566 +    def BodyPreamble(self, name, header_file):
  1.1567 +        global _NAME
  1.1568 +        global _VERSION
  1.1569 +
  1.1570 +        slash = header_file.rfind('/')
  1.1571 +        if slash != -1:
  1.1572 +            header_file = header_file[slash+1:]
  1.1573 +
  1.1574 +        pre = ( '/*\n'
  1.1575 +                ' * Automatically generated from %s\n'
  1.1576 +                ' * by %s/%s.  DO NOT EDIT THIS FILE.\n'
  1.1577 +                ' */\n\n' ) % (name, _NAME, _VERSION)
  1.1578 +        pre += ( '#include <stdlib.h>\n'
  1.1579 +                 '#include <string.h>\n'
  1.1580 +                 '#include <assert.h>\n'
  1.1581 +                 '#include <event2/event-config.h>\n'
  1.1582 +                 '#include <event2/event.h>\n'
  1.1583 +                 '#include <event2/buffer.h>\n'
  1.1584 +                 '#include <event2/tag.h>\n\n'
  1.1585 +                 '#ifdef _EVENT___func__\n'
  1.1586 +                 '#define __func__ _EVENT___func__\n'
  1.1587 +                 '#endif\n\n'
  1.1588 +                 )
  1.1589 +
  1.1590 +        for statement in cppdirect:
  1.1591 +            pre += '%s\n' % statement
  1.1592 +
  1.1593 +        pre += '\n#include "%s"\n\n' % header_file
  1.1594 +
  1.1595 +        pre += 'void event_warn(const char *fmt, ...);\n'
  1.1596 +        pre += 'void event_warnx(const char *fmt, ...);\n\n'
  1.1597 +
  1.1598 +        return pre
  1.1599 +
  1.1600 +    def HeaderFilename(self, filename):
  1.1601 +        return '.'.join(filename.split('.')[:-1]) + '.h'
  1.1602 +
  1.1603 +    def CodeFilename(self, filename):
  1.1604 +        return '.'.join(filename.split('.')[:-1]) + '.gen.c'
  1.1605 +
  1.1606 +    def Struct(self, name):
  1.1607 +        return StructCCode(name)
  1.1608 +
  1.1609 +    def EntryBytes(self, entry_type, name, tag, fixed_length):
  1.1610 +        return EntryBytes(entry_type, name, tag, fixed_length)
  1.1611 +
  1.1612 +    def EntryVarBytes(self, entry_type, name, tag):
  1.1613 +        return EntryVarBytes(entry_type, name, tag)
  1.1614 +
  1.1615 +    def EntryInt(self, entry_type, name, tag, bits=32):
  1.1616 +        return EntryInt(entry_type, name, tag, bits)
  1.1617 +
  1.1618 +    def EntryString(self, entry_type, name, tag):
  1.1619 +        return EntryString(entry_type, name, tag)
  1.1620 +
  1.1621 +    def EntryStruct(self, entry_type, name, tag, struct_name):
  1.1622 +        return EntryStruct(entry_type, name, tag, struct_name)
  1.1623 +
  1.1624 +    def EntryArray(self, entry):
  1.1625 +        return EntryArray(entry)
  1.1626 +
  1.1627 +class Usage(RpcGenError):
  1.1628 +    def __init__(self, argv0):
  1.1629 +        RpcGenError.__init__("usage: %s input.rpc [[output.h] output.c]"
  1.1630 +                             % argv0)
  1.1631 +
  1.1632 +class CommandLine:
  1.1633 +    def __init__(self, argv):
  1.1634 +        """Initialize a command-line to launch event_rpcgen, as if
  1.1635 +           from a command-line with CommandLine(sys.argv).  If you're
  1.1636 +           calling this directly, remember to provide a dummy value
  1.1637 +           for sys.argv[0]
  1.1638 +        """
  1.1639 +        self.filename = None
  1.1640 +        self.header_file = None
  1.1641 +        self.impl_file = None
  1.1642 +        self.factory = CCodeGenerator()
  1.1643 +
  1.1644 +        if len(argv) < 2 or len(argv) > 4:
  1.1645 +            raise Usage(argv[0])
  1.1646 +
  1.1647 +        self.filename = argv[1].replace('\\', '/')
  1.1648 +        if len(argv) == 3:
  1.1649 +            self.impl_file = argv[2].replace('\\', '/')
  1.1650 +        if len(argv) == 4:
  1.1651 +            self.header_file = argv[2].replace('\\', '/')
  1.1652 +            self.impl_file = argv[3].replace('\\', '/')
  1.1653 +
  1.1654 +        if not self.filename:
  1.1655 +            raise Usage(argv[0])
  1.1656 +
  1.1657 +        if not self.impl_file:
  1.1658 +            self.impl_file = self.factory.CodeFilename(self.filename)
  1.1659 +
  1.1660 +        if not self.header_file:
  1.1661 +            self.header_file = self.factory.HeaderFilename(self.impl_file)
  1.1662 +
  1.1663 +        if not self.impl_file.endswith('.c'):
  1.1664 +            raise RpcGenError("can only generate C implementation files")
  1.1665 +        if not self.header_file.endswith('.h'):
  1.1666 +            raise RpcGenError("can only generate C header files")
  1.1667 +
  1.1668 +    def run(self):
  1.1669 +        filename = self.filename
  1.1670 +        header_file = self.header_file
  1.1671 +        impl_file = self.impl_file
  1.1672 +        factory = self.factory
  1.1673 +
  1.1674 +        print >>sys.stderr, 'Reading \"%s\"' % filename
  1.1675 +
  1.1676 +        fp = open(filename, 'r')
  1.1677 +        entities = Parse(factory, fp)
  1.1678 +        fp.close()
  1.1679 +
  1.1680 +        print >>sys.stderr, '... creating "%s"' % header_file
  1.1681 +        header_fp = open(header_file, 'w')
  1.1682 +        print >>header_fp, factory.HeaderPreamble(filename)
  1.1683 +
  1.1684 +        # Create forward declarations: allows other structs to reference
  1.1685 +        # each other
  1.1686 +        for entry in entities:
  1.1687 +            entry.PrintForwardDeclaration(header_fp)
  1.1688 +        print >>header_fp, ''
  1.1689 +
  1.1690 +        for entry in entities:
  1.1691 +            entry.PrintTags(header_fp)
  1.1692 +            entry.PrintDeclaration(header_fp)
  1.1693 +        print >>header_fp, factory.HeaderPostamble(filename)
  1.1694 +        header_fp.close()
  1.1695 +
  1.1696 +        print >>sys.stderr, '... creating "%s"' % impl_file
  1.1697 +        impl_fp = open(impl_file, 'w')
  1.1698 +        print >>impl_fp, factory.BodyPreamble(filename, header_file)
  1.1699 +        for entry in entities:
  1.1700 +            entry.PrintCode(impl_fp)
  1.1701 +        impl_fp.close()
  1.1702 +
  1.1703 +if __name__ == '__main__':
  1.1704 +    try:
  1.1705 +        CommandLine(sys.argv).run()
  1.1706 +        sys.exit(0)
  1.1707 +
  1.1708 +    except RpcGenError, e:
  1.1709 +        print >>sys.stderr, e
  1.1710 +        sys.exit(1)
  1.1711 +
  1.1712 +    except EnvironmentError, e:
  1.1713 +        if e.filename and e.strerror:
  1.1714 +            print >>sys.stderr, "%s: %s" % (e.filename, e.strerror)
  1.1715 +            sys.exit(1)
  1.1716 +        elif e.strerror:
  1.1717 +            print >> sys.stderr, e.strerror
  1.1718 +            sys.exit(1)
  1.1719 +        else:
  1.1720 +            raise

mercurial