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