1#!/usr/bin/env python 2# 3# Copyright (c) 2005-2007 Niels Provos <provos@citi.umich.edu> 4# Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 5# All rights reserved. 6# 7# Generates marshaling code based on libevent. 8 9# TODO: 10# 1) use optparse to allow the strategy shell to parse options, and 11# to allow the instantiated factory (for the specific output language) 12# to parse remaining options 13# 2) move the globals into a class that manages execution (including the 14# progress outputs that space stderr at the moment) 15# 3) emit other languages 16 17import sys 18import re 19 20_NAME = "event_rpcgen.py" 21_VERSION = "0.1" 22 23# Globals 24line_count = 0 25 26white = re.compile(r'\s+') 27cppcomment = re.compile(r'\/\/.*$') 28nonident = re.compile(r'[^a-zA-Z0-9_]') 29structref = re.compile(r'^struct\[([a-zA-Z_][a-zA-Z0-9_]*)\]$') 30structdef = re.compile(r'^struct +[a-zA-Z_][a-zA-Z0-9_]* *{$') 31 32headerdirect = [] 33cppdirect = [] 34 35QUIETLY = 0 36 37def declare(s): 38 if not QUIETLY: 39 print(s) 40 41def TranslateList(mylist, mydict): 42 return [x % mydict for x in mylist] 43 44# Exception class for parse errors 45class RpcGenError(Exception): 46 def __init__(self, why): 47 self.why = why 48 def __str__(self): 49 return str(self.why) 50 51# Holds everything that makes a struct 52class Struct: 53 def __init__(self, name): 54 self._name = name 55 self._entries = [] 56 self._tags = {} 57 declare(' Created struct: %s' % name) 58 59 def AddEntry(self, entry): 60 if entry.Tag() in self._tags: 61 raise RpcGenError( 62 'Entry "%s" duplicates tag number %d from "%s" ' 63 'around line %d' % (entry.Name(), entry.Tag(), 64 self._tags[entry.Tag()], line_count)) 65 self._entries.append(entry) 66 self._tags[entry.Tag()] = entry.Name() 67 declare(' Added entry: %s' % entry.Name()) 68 69 def Name(self): 70 return self._name 71 72 def EntryTagName(self, entry): 73 """Creates the name inside an enumeration for distinguishing data 74 types.""" 75 name = "%s_%s" % (self._name, entry.Name()) 76 return name.upper() 77 78 def PrintIndented(self, file, ident, code): 79 """Takes an array, add indentation to each entry and prints it.""" 80 for entry in code: 81 file.write('%s%s\n' % (ident, entry)) 82 83class StructCCode(Struct): 84 """ Knows how to generate C code for a struct """ 85 86 def __init__(self, name): 87 Struct.__init__(self, name) 88 89 def PrintTags(self, file): 90 """Prints the tag definitions for a structure.""" 91 file.write('/* Tag definition for %s */\n' % self._name) 92 file.write('enum %s_ {\n' % self._name.lower()) 93 for entry in self._entries: 94 file.write(' %s=%d,\n' % (self.EntryTagName(entry), entry.Tag())) 95 file.write(' %s_MAX_TAGS\n' % (self._name.upper())) 96 file.write('};\n\n') 97 98 def PrintForwardDeclaration(self, file): 99 file.write('struct %s;\n' % self._name) 100 101 def PrintDeclaration(self, file): 102 file.write('/* Structure declaration for %s */\n' % self._name) 103 file.write('struct %s_access_ {\n' % self._name) 104 for entry in self._entries: 105 dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name()) 106 dcl.extend( 107 entry.GetDeclaration('(*%s_get)' % entry.Name())) 108 if entry.Array(): 109 dcl.extend( 110 entry.AddDeclaration('(*%s_add)' % entry.Name())) 111 self.PrintIndented(file, ' ', dcl) 112 file.write('};\n\n') 113 114 file.write('struct %s {\n' % self._name) 115 file.write(' struct %s_access_ *base;\n\n' % self._name) 116 for entry in self._entries: 117 dcl = entry.Declaration() 118 self.PrintIndented(file, ' ', dcl) 119 file.write('\n') 120 for entry in self._entries: 121 file.write(' ev_uint8_t %s_set;\n' % entry.Name()) 122 file.write('};\n\n') 123 124 file.write("""struct %(name)s *%(name)s_new(void); 125struct %(name)s *%(name)s_new_with_arg(void *); 126void %(name)s_free(struct %(name)s *); 127void %(name)s_clear(struct %(name)s *); 128void %(name)s_marshal(struct evbuffer *, const struct %(name)s *); 129int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *); 130int %(name)s_complete(struct %(name)s *); 131void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t, 132 const struct %(name)s *); 133int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t, 134 struct %(name)s *);\n""" % { 'name' : self._name }) 135 136 137 # Write a setting function of every variable 138 for entry in self._entries: 139 self.PrintIndented(file, '', entry.AssignDeclaration( 140 entry.AssignFuncName())) 141 self.PrintIndented(file, '', entry.GetDeclaration( 142 entry.GetFuncName())) 143 if entry.Array(): 144 self.PrintIndented(file, '', entry.AddDeclaration( 145 entry.AddFuncName())) 146 147 file.write('/* --- %s done --- */\n\n' % self._name) 148 149 def PrintCode(self, file): 150 file.write(('/*\n' 151 ' * Implementation of %s\n' 152 ' */\n\n') % self._name) 153 154 file.write('static struct %(name)s_access_ %(name)s_base__ = {\n' % \ 155 { 'name' : self._name }) 156 for entry in self._entries: 157 self.PrintIndented(file, ' ', entry.CodeBase()) 158 file.write('};\n\n') 159 160 # Creation 161 file.write(( 162 'struct %(name)s *\n' 163 '%(name)s_new(void)\n' 164 '{\n' 165 ' return %(name)s_new_with_arg(NULL);\n' 166 '}\n' 167 '\n' 168 'struct %(name)s *\n' 169 '%(name)s_new_with_arg(void *unused)\n' 170 '{\n' 171 ' struct %(name)s *tmp;\n' 172 ' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n' 173 ' event_warn("%%s: malloc", __func__);\n' 174 ' return (NULL);\n' 175 ' }\n' 176 ' tmp->base = &%(name)s_base__;\n\n') % { 'name' : self._name }) 177 178 for entry in self._entries: 179 self.PrintIndented(file, ' ', entry.CodeInitialize('tmp')) 180 file.write(' tmp->%s_set = 0;\n\n' % entry.Name()) 181 182 file.write(( 183 ' return (tmp);\n' 184 '}\n\n')) 185 186 # Adding 187 for entry in self._entries: 188 if entry.Array(): 189 self.PrintIndented(file, '', entry.CodeAdd()) 190 file.write('\n') 191 192 # Assigning 193 for entry in self._entries: 194 self.PrintIndented(file, '', entry.CodeAssign()) 195 file.write('\n') 196 197 # Getting 198 for entry in self._entries: 199 self.PrintIndented(file, '', entry.CodeGet()) 200 file.write('\n') 201 202 # Clearing 203 file.write(( 'void\n' 204 '%(name)s_clear(struct %(name)s *tmp)\n' 205 '{' 206 '\n') % { 'name' : self._name }) 207 for entry in self._entries: 208 self.PrintIndented(file, ' ', entry.CodeClear('tmp')) 209 210 file.write('}\n\n') 211 212 # Freeing 213 file.write(( 'void\n' 214 '%(name)s_free(struct %(name)s *tmp)\n' 215 '{' 216 '\n') % { 'name' : self._name }) 217 218 for entry in self._entries: 219 self.PrintIndented(file, ' ', entry.CodeFree('tmp')) 220 221 file.write((' free(tmp);\n' 222 '}\n\n')) 223 224 # Marshaling 225 file.write(('void\n' 226 '%(name)s_marshal(struct evbuffer *evbuf, ' 227 'const struct %(name)s *tmp)' 228 '{\n') % { 'name' : self._name }) 229 for entry in self._entries: 230 indent = ' ' 231 # Optional entries do not have to be set 232 if entry.Optional(): 233 indent += ' ' 234 file.write(' if (tmp->%s_set) {\n' % entry.Name()) 235 self.PrintIndented( 236 file, indent, 237 entry.CodeMarshal('evbuf', self.EntryTagName(entry), 238 entry.GetVarName('tmp'), 239 entry.GetVarLen('tmp'))) 240 if entry.Optional(): 241 file.write(' }\n') 242 243 file.write('}\n\n') 244 245 # Unmarshaling 246 file.write(('int\n' 247 '%(name)s_unmarshal(struct %(name)s *tmp, ' 248 ' struct evbuffer *evbuf)\n' 249 '{\n' 250 ' ev_uint32_t tag;\n' 251 ' while (evbuffer_get_length(evbuf) > 0) {\n' 252 ' if (evtag_peek(evbuf, &tag) == -1)\n' 253 ' return (-1);\n' 254 ' switch (tag) {\n' 255 '\n') % { 'name' : self._name }) 256 for entry in self._entries: 257 file.write(' case %s:\n' % self.EntryTagName(entry)) 258 if not entry.Array(): 259 file.write(( 260 ' if (tmp->%s_set)\n' 261 ' return (-1);' 262 '\n') % (entry.Name())) 263 264 self.PrintIndented( 265 file, ' ', 266 entry.CodeUnmarshal('evbuf', 267 self.EntryTagName(entry), 268 entry.GetVarName('tmp'), 269 entry.GetVarLen('tmp'))) 270 271 file.write(( ' tmp->%s_set = 1;\n' % entry.Name() + 272 ' break;\n' )) 273 file.write(( ' default:\n' 274 ' return -1;\n' 275 ' }\n' 276 ' }\n\n' )) 277 # Check if it was decoded completely 278 file.write(( ' if (%(name)s_complete(tmp) == -1)\n' 279 ' return (-1);' 280 '\n') % { 'name' : self._name }) 281 282 # Successfully decoded 283 file.write(( ' return (0);\n' 284 '}\n\n')) 285 286 # Checking if a structure has all the required data 287 file.write(( 288 'int\n' 289 '%(name)s_complete(struct %(name)s *msg)\n' 290 '{\n' ) % { 'name' : self._name }) 291 for entry in self._entries: 292 if not entry.Optional(): 293 code = [ 294 'if (!msg->%(name)s_set)', 295 ' return (-1);' ] 296 code = TranslateList(code, entry.GetTranslation()) 297 self.PrintIndented( 298 file, ' ', code) 299 300 self.PrintIndented( 301 file, ' ', 302 entry.CodeComplete('msg', entry.GetVarName('msg'))) 303 file.write(( 304 ' return (0);\n' 305 '}\n\n' )) 306 307 # Complete message unmarshaling 308 file.write(( 309 'int\n' 310 'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, ' 311 'ev_uint32_t need_tag, struct %(name)s *msg)\n' 312 '{\n' 313 ' ev_uint32_t tag;\n' 314 ' int res = -1;\n' 315 '\n' 316 ' struct evbuffer *tmp = evbuffer_new();\n' 317 '\n' 318 ' if (evtag_unmarshal(evbuf, &tag, tmp) == -1' 319 ' || tag != need_tag)\n' 320 ' goto error;\n' 321 '\n' 322 ' if (%(name)s_unmarshal(msg, tmp) == -1)\n' 323 ' goto error;\n' 324 '\n' 325 ' res = 0;\n' 326 '\n' 327 ' error:\n' 328 ' evbuffer_free(tmp);\n' 329 ' return (res);\n' 330 '}\n\n' ) % { 'name' : self._name }) 331 332 # Complete message marshaling 333 file.write(( 334 'void\n' 335 'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, ' 336 'const struct %(name)s *msg)\n' 337 '{\n' 338 ' struct evbuffer *buf_ = evbuffer_new();\n' 339 ' assert(buf_ != NULL);\n' 340 ' %(name)s_marshal(buf_, msg);\n' 341 ' evtag_marshal_buffer(evbuf, tag, buf_);\n ' 342 ' evbuffer_free(buf_);\n' 343 '}\n\n' ) % { 'name' : self._name }) 344 345class Entry: 346 def __init__(self, type, name, tag): 347 self._type = type 348 self._name = name 349 self._tag = int(tag) 350 self._ctype = type 351 self._optional = 0 352 self._can_be_array = 0 353 self._array = 0 354 self._line_count = -1 355 self._struct = None 356 self._refname = None 357 358 self._optpointer = True 359 self._optaddarg = True 360 361 def GetInitializer(self): 362 assert 0, "Entry does not provide initializer" 363 364 def SetStruct(self, struct): 365 self._struct = struct 366 367 def LineCount(self): 368 assert self._line_count != -1 369 return self._line_count 370 371 def SetLineCount(self, number): 372 self._line_count = number 373 374 def Array(self): 375 return self._array 376 377 def Optional(self): 378 return self._optional 379 380 def Tag(self): 381 return self._tag 382 383 def Name(self): 384 return self._name 385 386 def Type(self): 387 return self._type 388 389 def MakeArray(self, yes=1): 390 self._array = yes 391 392 def MakeOptional(self): 393 self._optional = 1 394 395 def Verify(self): 396 if self.Array() and not self._can_be_array: 397 raise RpcGenError( 398 'Entry "%s" cannot be created as an array ' 399 'around line %d' % (self._name, self.LineCount())) 400 if not self._struct: 401 raise RpcGenError( 402 'Entry "%s" does not know which struct it belongs to ' 403 'around line %d' % (self._name, self.LineCount())) 404 if self._optional and self._array: 405 raise RpcGenError( 406 'Entry "%s" has illegal combination of optional and array ' 407 'around line %d' % (self._name, self.LineCount())) 408 409 def GetTranslation(self, extradict = {}): 410 mapping = { 411 "parent_name" : self._struct.Name(), 412 "name" : self._name, 413 "ctype" : self._ctype, 414 "refname" : self._refname, 415 "optpointer" : self._optpointer and "*" or "", 416 "optreference" : self._optpointer and "&" or "", 417 "optaddarg" : 418 self._optaddarg and ", const %s value" % self._ctype or "" 419 } 420 for (k, v) in list(extradict.items()): 421 mapping[k] = v 422 423 return mapping 424 425 def GetVarName(self, var): 426 return '%(var)s->%(name)s_data' % self.GetTranslation({ 'var' : var }) 427 428 def GetVarLen(self, var): 429 return 'sizeof(%s)' % self._ctype 430 431 def GetFuncName(self): 432 return '%s_%s_get' % (self._struct.Name(), self._name) 433 434 def GetDeclaration(self, funcname): 435 code = [ 'int %s(struct %s *, %s *);' % ( 436 funcname, self._struct.Name(), self._ctype ) ] 437 return code 438 439 def CodeGet(self): 440 code = ( 441 'int', 442 '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, ' 443 '%(ctype)s *value)', 444 '{', 445 ' if (msg->%(name)s_set != 1)', 446 ' return (-1);', 447 ' *value = msg->%(name)s_data;', 448 ' return (0);', 449 '}' ) 450 code = '\n'.join(code) 451 code = code % self.GetTranslation() 452 return code.split('\n') 453 454 def AssignFuncName(self): 455 return '%s_%s_assign' % (self._struct.Name(), self._name) 456 457 def AddFuncName(self): 458 return '%s_%s_add' % (self._struct.Name(), self._name) 459 460 def AssignDeclaration(self, funcname): 461 code = [ 'int %s(struct %s *, const %s);' % ( 462 funcname, self._struct.Name(), self._ctype ) ] 463 return code 464 465 def CodeAssign(self): 466 code = [ 'int', 467 '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,' 468 ' const %(ctype)s value)', 469 '{', 470 ' msg->%(name)s_set = 1;', 471 ' msg->%(name)s_data = value;', 472 ' return (0);', 473 '}' ] 474 code = '\n'.join(code) 475 code = code % self.GetTranslation() 476 return code.split('\n') 477 478 def CodeClear(self, structname): 479 code = [ '%s->%s_set = 0;' % (structname, self.Name()) ] 480 481 return code 482 483 def CodeComplete(self, structname, var_name): 484 return [] 485 486 def CodeFree(self, name): 487 return [] 488 489 def CodeBase(self): 490 code = [ 491 '%(parent_name)s_%(name)s_assign,', 492 '%(parent_name)s_%(name)s_get,' 493 ] 494 if self.Array(): 495 code.append('%(parent_name)s_%(name)s_add,') 496 497 code = '\n'.join(code) 498 code = code % self.GetTranslation() 499 return code.split('\n') 500 501class EntryBytes(Entry): 502 def __init__(self, type, name, tag, length): 503 # Init base class 504 Entry.__init__(self, type, name, tag) 505 506 self._length = length 507 self._ctype = 'ev_uint8_t' 508 509 def GetInitializer(self): 510 return "NULL" 511 512 def GetVarLen(self, var): 513 return '(%s)' % self._length 514 515 def CodeArrayAdd(self, varname, value): 516 # XXX: copy here 517 return [ '%(varname)s = NULL;' % { 'varname' : varname } ] 518 519 def GetDeclaration(self, funcname): 520 code = [ 'int %s(struct %s *, %s **);' % ( 521 funcname, self._struct.Name(), self._ctype ) ] 522 return code 523 524 def AssignDeclaration(self, funcname): 525 code = [ 'int %s(struct %s *, const %s *);' % ( 526 funcname, self._struct.Name(), self._ctype ) ] 527 return code 528 529 def Declaration(self): 530 dcl = ['ev_uint8_t %s_data[%s];' % (self._name, self._length)] 531 532 return dcl 533 534 def CodeGet(self): 535 name = self._name 536 code = [ 'int', 537 '%s_%s_get(struct %s *msg, %s **value)' % ( 538 self._struct.Name(), name, 539 self._struct.Name(), self._ctype), 540 '{', 541 ' if (msg->%s_set != 1)' % name, 542 ' return (-1);', 543 ' *value = msg->%s_data;' % name, 544 ' return (0);', 545 '}' ] 546 return code 547 548 def CodeAssign(self): 549 name = self._name 550 code = [ 'int', 551 '%s_%s_assign(struct %s *msg, const %s *value)' % ( 552 self._struct.Name(), name, 553 self._struct.Name(), self._ctype), 554 '{', 555 ' msg->%s_set = 1;' % name, 556 ' memcpy(msg->%s_data, value, %s);' % ( 557 name, self._length), 558 ' return (0);', 559 '}' ] 560 return code 561 562 def CodeUnmarshal(self, buf, tag_name, var_name, var_len): 563 code = [ 'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, ' 564 '%(var)s, %(varlen)s) == -1) {', 565 ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', 566 ' return (-1);', 567 '}' 568 ] 569 return TranslateList(code, 570 self.GetTranslation({ 571 'var' : var_name, 572 'varlen' : var_len, 573 'buf' : buf, 574 'tag' : tag_name })) 575 576 def CodeMarshal(self, buf, tag_name, var_name, var_len): 577 code = ['evtag_marshal(%s, %s, %s, %s);' % ( 578 buf, tag_name, var_name, var_len)] 579 return code 580 581 def CodeClear(self, structname): 582 code = [ '%s->%s_set = 0;' % (structname, self.Name()), 583 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( 584 structname, self._name, structname, self._name)] 585 586 return code 587 588 def CodeInitialize(self, name): 589 code = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( 590 name, self._name, name, self._name)] 591 return code 592 593 def Verify(self): 594 if not self._length: 595 raise RpcGenError( 596 'Entry "%s" needs a length ' 597 'around line %d' % (self._name, self.LineCount())) 598 599 Entry.Verify(self) 600 601class EntryInt(Entry): 602 def __init__(self, type, name, tag, bits=32): 603 # Init base class 604 Entry.__init__(self, type, name, tag) 605 606 self._can_be_array = 1 607 if bits == 32: 608 self._ctype = 'ev_uint32_t' 609 self._marshal_type = 'int' 610 if bits == 64: 611 self._ctype = 'ev_uint64_t' 612 self._marshal_type = 'int64' 613 614 def GetInitializer(self): 615 return "0" 616 617 def CodeArrayFree(self, var): 618 return [] 619 620 def CodeArrayAssign(self, varname, srcvar): 621 return [ '%(varname)s = %(srcvar)s;' % { 'varname' : varname, 622 'srcvar' : srcvar } ] 623 624 def CodeArrayAdd(self, varname, value): 625 """Returns a new entry of this type.""" 626 return [ '%(varname)s = %(value)s;' % { 'varname' : varname, 627 'value' : value } ] 628 629 def CodeUnmarshal(self, buf, tag_name, var_name, var_len): 630 code = [ 631 'if (evtag_unmarshal_%(ma)s(%(buf)s, %(tag)s, &%(var)s) == -1) {', 632 ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', 633 ' return (-1);', 634 '}' ] 635 code = '\n'.join(code) % self.GetTranslation({ 636 'ma' : self._marshal_type, 637 'buf' : buf, 638 'tag' : tag_name, 639 'var' : var_name }) 640 return code.split('\n') 641 642 def CodeMarshal(self, buf, tag_name, var_name, var_len): 643 code = [ 644 'evtag_marshal_%s(%s, %s, %s);' % ( 645 self._marshal_type, buf, tag_name, var_name)] 646 return code 647 648 def Declaration(self): 649 dcl = ['%s %s_data;' % (self._ctype, self._name)] 650 651 return dcl 652 653 def CodeInitialize(self, name): 654 code = ['%s->%s_data = 0;' % (name, self._name)] 655 return code 656 657class EntryString(Entry): 658 def __init__(self, type, name, tag): 659 # Init base class 660 Entry.__init__(self, type, name, tag) 661 662 self._can_be_array = 1 663 self._ctype = 'char *' 664 665 def GetInitializer(self): 666 return "NULL" 667 668 def CodeArrayFree(self, varname): 669 code = [ 670 'if (%(var)s != NULL) free(%(var)s);' ] 671 672 return TranslateList(code, { 'var' : varname }) 673 674 def CodeArrayAssign(self, varname, srcvar): 675 code = [ 676 'if (%(var)s != NULL)', 677 ' free(%(var)s);', 678 '%(var)s = strdup(%(srcvar)s);', 679 'if (%(var)s == NULL) {', 680 ' event_warnx("%%s: strdup", __func__);', 681 ' return (-1);', 682 '}' ] 683 684 return TranslateList(code, { 'var' : varname, 685 'srcvar' : srcvar }) 686 687 def CodeArrayAdd(self, varname, value): 688 code = [ 689 'if (%(value)s != NULL) {', 690 ' %(var)s = strdup(%(value)s);', 691 ' if (%(var)s == NULL) {', 692 ' goto error;', 693 ' }', 694 '} else {', 695 ' %(var)s = NULL;', 696 '}' ] 697 698 return TranslateList(code, { 'var' : varname, 699 'value' : value }) 700 701 def GetVarLen(self, var): 702 return 'strlen(%s)' % self.GetVarName(var) 703 704 def CodeMakeInitalize(self, varname): 705 return '%(varname)s = NULL;' % { 'varname' : varname } 706 707 def CodeAssign(self): 708 name = self._name 709 code = """int 710%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, 711 const %(ctype)s value) 712{ 713 if (msg->%(name)s_data != NULL) 714 free(msg->%(name)s_data); 715 if ((msg->%(name)s_data = strdup(value)) == NULL) 716 return (-1); 717 msg->%(name)s_set = 1; 718 return (0); 719}""" % self.GetTranslation() 720 721 return code.split('\n') 722 723 def CodeUnmarshal(self, buf, tag_name, var_name, var_len): 724 code = ['if (evtag_unmarshal_string(%(buf)s, %(tag)s, &%(var)s) == -1) {', 725 ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', 726 ' return (-1);', 727 '}' 728 ] 729 code = '\n'.join(code) % self.GetTranslation({ 730 'buf' : buf, 731 'tag' : tag_name, 732 'var' : var_name }) 733 return code.split('\n') 734 735 def CodeMarshal(self, buf, tag_name, var_name, var_len): 736 code = ['evtag_marshal_string(%s, %s, %s);' % ( 737 buf, tag_name, var_name)] 738 return code 739 740 def CodeClear(self, structname): 741 code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), 742 ' free(%s->%s_data);' % (structname, self.Name()), 743 ' %s->%s_data = NULL;' % (structname, self.Name()), 744 ' %s->%s_set = 0;' % (structname, self.Name()), 745 '}' 746 ] 747 748 return code 749 750 def CodeInitialize(self, name): 751 code = ['%s->%s_data = NULL;' % (name, self._name)] 752 return code 753 754 def CodeFree(self, name): 755 code = ['if (%s->%s_data != NULL)' % (name, self._name), 756 ' free (%s->%s_data);' % (name, self._name)] 757 758 return code 759 760 def Declaration(self): 761 dcl = ['char *%s_data;' % self._name] 762 763 return dcl 764 765class EntryStruct(Entry): 766 def __init__(self, type, name, tag, refname): 767 # Init base class 768 Entry.__init__(self, type, name, tag) 769 770 self._optpointer = False 771 self._can_be_array = 1 772 self._refname = refname 773 self._ctype = 'struct %s*' % refname 774 self._optaddarg = False 775 776 def GetInitializer(self): 777 return "NULL" 778 779 def GetVarLen(self, var): 780 return '-1' 781 782 def CodeArrayAdd(self, varname, value): 783 code = [ 784 '%(varname)s = %(refname)s_new();', 785 'if (%(varname)s == NULL)', 786 ' goto error;' ] 787 788 return TranslateList(code, self.GetTranslation({ 'varname' : varname })) 789 790 def CodeArrayFree(self, var): 791 code = [ '%(refname)s_free(%(var)s);' % self.GetTranslation( 792 { 'var' : var }) ] 793 return code 794 795 def CodeArrayAssign(self, var, srcvar): 796 code = [ 797 'int had_error = 0;', 798 'struct evbuffer *tmp = NULL;', 799 '%(refname)s_clear(%(var)s);', 800 'if ((tmp = evbuffer_new()) == NULL) {', 801 ' event_warn("%%s: evbuffer_new()", __func__);', 802 ' had_error = 1;', 803 ' goto done;', 804 '}', 805 '%(refname)s_marshal(tmp, %(srcvar)s);', 806 'if (%(refname)s_unmarshal(%(var)s, tmp) == -1) {', 807 ' event_warnx("%%s: %(refname)s_unmarshal", __func__);', 808 ' had_error = 1;', 809 ' goto done;', 810 '}', 811 'done:' 812 'if (tmp != NULL)', 813 ' evbuffer_free(tmp);', 814 'if (had_error) {', 815 ' %(refname)s_clear(%(var)s);', 816 ' return (-1);', 817 '}' ] 818 819 return TranslateList(code, self.GetTranslation({ 820 'var' : var, 821 'srcvar' : srcvar})) 822 823 def CodeGet(self): 824 name = self._name 825 code = [ 'int', 826 '%s_%s_get(struct %s *msg, %s *value)' % ( 827 self._struct.Name(), name, 828 self._struct.Name(), self._ctype), 829 '{', 830 ' if (msg->%s_set != 1) {' % name, 831 ' msg->%s_data = %s_new();' % (name, self._refname), 832 ' if (msg->%s_data == NULL)' % name, 833 ' return (-1);', 834 ' msg->%s_set = 1;' % name, 835 ' }', 836 ' *value = msg->%s_data;' % name, 837 ' return (0);', 838 '}' ] 839 return code 840 841 def CodeAssign(self): 842 name = self._name 843 code = """int 844%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, 845 const %(ctype)s value) 846{ 847 struct evbuffer *tmp = NULL; 848 if (msg->%(name)s_set) { 849 %(refname)s_clear(msg->%(name)s_data); 850 msg->%(name)s_set = 0; 851 } else { 852 msg->%(name)s_data = %(refname)s_new(); 853 if (msg->%(name)s_data == NULL) { 854 event_warn("%%s: %(refname)s_new()", __func__); 855 goto error; 856 } 857 } 858 if ((tmp = evbuffer_new()) == NULL) { 859 event_warn("%%s: evbuffer_new()", __func__); 860 goto error; 861 } 862 %(refname)s_marshal(tmp, value); 863 if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) { 864 event_warnx("%%s: %(refname)s_unmarshal", __func__); 865 goto error; 866 } 867 msg->%(name)s_set = 1; 868 evbuffer_free(tmp); 869 return (0); 870 error: 871 if (tmp != NULL) 872 evbuffer_free(tmp); 873 if (msg->%(name)s_data != NULL) { 874 %(refname)s_free(msg->%(name)s_data); 875 msg->%(name)s_data = NULL; 876 } 877 return (-1); 878}""" % self.GetTranslation() 879 return code.split('\n') 880 881 def CodeComplete(self, structname, var_name): 882 code = [ 'if (%(structname)s->%(name)s_set && ' 883 '%(refname)s_complete(%(var)s) == -1)', 884 ' return (-1);' ] 885 886 return TranslateList(code, self.GetTranslation({ 887 'structname' : structname, 888 'var' : var_name })) 889 890 def CodeUnmarshal(self, buf, tag_name, var_name, var_len): 891 code = ['%(var)s = %(refname)s_new();', 892 'if (%(var)s == NULL)', 893 ' return (-1);', 894 'if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag)s, ' 895 '%(var)s) == -1) {', 896 ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', 897 ' return (-1);', 898 '}' 899 ] 900 code = '\n'.join(code) % self.GetTranslation({ 901 'buf' : buf, 902 'tag' : tag_name, 903 'var' : var_name }) 904 return code.split('\n') 905 906 def CodeMarshal(self, buf, tag_name, var_name, var_len): 907 code = ['evtag_marshal_%s(%s, %s, %s);' % ( 908 self._refname, buf, tag_name, var_name)] 909 return code 910 911 def CodeClear(self, structname): 912 code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), 913 ' %s_free(%s->%s_data);' % ( 914 self._refname, structname, self.Name()), 915 ' %s->%s_data = NULL;' % (structname, self.Name()), 916 ' %s->%s_set = 0;' % (structname, self.Name()), 917 '}' 918 ] 919 920 return code 921 922 def CodeInitialize(self, name): 923 code = ['%s->%s_data = NULL;' % (name, self._name)] 924 return code 925 926 def CodeFree(self, name): 927 code = ['if (%s->%s_data != NULL)' % (name, self._name), 928 ' %s_free(%s->%s_data);' % ( 929 self._refname, name, self._name)] 930 931 return code 932 933 def Declaration(self): 934 dcl = ['%s %s_data;' % (self._ctype, self._name)] 935 936 return dcl 937 938class EntryVarBytes(Entry): 939 def __init__(self, type, name, tag): 940 # Init base class 941 Entry.__init__(self, type, name, tag) 942 943 self._ctype = 'ev_uint8_t *' 944 945 def GetInitializer(self): 946 return "NULL" 947 948 def GetVarLen(self, var): 949 return '%(var)s->%(name)s_length' % self.GetTranslation({ 'var' : var }) 950 951 def CodeArrayAdd(self, varname, value): 952 # xxx: copy 953 return [ '%(varname)s = NULL;' % { 'varname' : varname } ] 954 955 def GetDeclaration(self, funcname): 956 code = [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % ( 957 funcname, self._struct.Name(), self._ctype ) ] 958 return code 959 960 def AssignDeclaration(self, funcname): 961 code = [ 'int %s(struct %s *, const %s, ev_uint32_t);' % ( 962 funcname, self._struct.Name(), self._ctype ) ] 963 return code 964 965 def CodeAssign(self): 966 name = self._name 967 code = [ 'int', 968 '%s_%s_assign(struct %s *msg, ' 969 'const %s value, ev_uint32_t len)' % ( 970 self._struct.Name(), name, 971 self._struct.Name(), self._ctype), 972 '{', 973 ' if (msg->%s_data != NULL)' % name, 974 ' free (msg->%s_data);' % name, 975 ' msg->%s_data = malloc(len);' % name, 976 ' if (msg->%s_data == NULL)' % name, 977 ' return (-1);', 978 ' msg->%s_set = 1;' % name, 979 ' msg->%s_length = len;' % name, 980 ' memcpy(msg->%s_data, value, len);' % name, 981 ' return (0);', 982 '}' ] 983 return code 984 985 def CodeGet(self): 986 name = self._name 987 code = [ 'int', 988 '%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)' % ( 989 self._struct.Name(), name, 990 self._struct.Name(), self._ctype), 991 '{', 992 ' if (msg->%s_set != 1)' % name, 993 ' return (-1);', 994 ' *value = msg->%s_data;' % name, 995 ' *plen = msg->%s_length;' % name, 996 ' return (0);', 997 '}' ] 998 return code 999 1000 def CodeUnmarshal(self, buf, tag_name, var_name, var_len): 1001 code = ['if (evtag_payload_length(%(buf)s, &%(varlen)s) == -1)', 1002 ' return (-1);', 1003 # We do not want DoS opportunities 1004 'if (%(varlen)s > evbuffer_get_length(%(buf)s))', 1005 ' return (-1);', 1006 'if ((%(var)s = malloc(%(varlen)s)) == NULL)', 1007 ' return (-1);', 1008 'if (evtag_unmarshal_fixed(%(buf)s, %(tag)s, %(var)s, ' 1009 '%(varlen)s) == -1) {', 1010 ' event_warnx("%%s: failed to unmarshal %(name)s", __func__);', 1011 ' return (-1);', 1012 '}' 1013 ] 1014 code = '\n'.join(code) % self.GetTranslation({ 1015 'buf' : buf, 1016 'tag' : tag_name, 1017 'var' : var_name, 1018 'varlen' : var_len }) 1019 return code.split('\n') 1020 1021 def CodeMarshal(self, buf, tag_name, var_name, var_len): 1022 code = ['evtag_marshal(%s, %s, %s, %s);' % ( 1023 buf, tag_name, var_name, var_len)] 1024 return code 1025 1026 def CodeClear(self, structname): 1027 code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), 1028 ' free (%s->%s_data);' % (structname, self.Name()), 1029 ' %s->%s_data = NULL;' % (structname, self.Name()), 1030 ' %s->%s_length = 0;' % (structname, self.Name()), 1031 ' %s->%s_set = 0;' % (structname, self.Name()), 1032 '}' 1033 ] 1034 1035 return code 1036 1037 def CodeInitialize(self, name): 1038 code = ['%s->%s_data = NULL;' % (name, self._name), 1039 '%s->%s_length = 0;' % (name, self._name) ] 1040 return code 1041 1042 def CodeFree(self, name): 1043 code = ['if (%s->%s_data != NULL)' % (name, self._name), 1044 ' free(%s->%s_data);' % (name, self._name)] 1045 1046 return code 1047 1048 def Declaration(self): 1049 dcl = ['ev_uint8_t *%s_data;' % self._name, 1050 'ev_uint32_t %s_length;' % self._name] 1051 1052 return dcl 1053 1054class EntryArray(Entry): 1055 def __init__(self, entry): 1056 # Init base class 1057 Entry.__init__(self, entry._type, entry._name, entry._tag) 1058 1059 self._entry = entry 1060 self._refname = entry._refname 1061 self._ctype = self._entry._ctype 1062 self._optional = True 1063 self._optpointer = self._entry._optpointer 1064 self._optaddarg = self._entry._optaddarg 1065 1066 # provide a new function for accessing the variable name 1067 def GetVarName(var_name): 1068 return '%(var)s->%(name)s_data[%(index)s]' % \ 1069 self._entry.GetTranslation({'var' : var_name, 1070 'index' : self._index}) 1071 self._entry.GetVarName = GetVarName 1072 1073 def GetInitializer(self): 1074 return "NULL" 1075 1076 def GetVarName(self, var_name): 1077 return var_name 1078 1079 def GetVarLen(self, var_name): 1080 return '-1' 1081 1082 def GetDeclaration(self, funcname): 1083 """Allows direct access to elements of the array.""" 1084 code = [ 1085 'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' % 1086 self.GetTranslation({ 'funcname' : funcname }) ] 1087 return code 1088 1089 def AssignDeclaration(self, funcname): 1090 code = [ 'int %s(struct %s *, int, const %s);' % ( 1091 funcname, self._struct.Name(), self._ctype ) ] 1092 return code 1093 1094 def AddDeclaration(self, funcname): 1095 code = [ 1096 '%(ctype)s %(optpointer)s ' 1097 '%(funcname)s(struct %(parent_name)s *msg%(optaddarg)s);' % \ 1098 self.GetTranslation({ 'funcname' : funcname }) ] 1099 return code 1100 1101 def CodeGet(self): 1102 code = """int 1103%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset, 1104 %(ctype)s *value) 1105{ 1106 if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length) 1107 return (-1); 1108 *value = msg->%(name)s_data[offset]; 1109 return (0); 1110}""" % self.GetTranslation() 1111 1112 return code.split('\n') 1113 1114 def CodeAssign(self): 1115 code = [ 1116 'int', 1117 '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,', 1118 ' const %(ctype)s value)', 1119 '{', 1120 ' if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)', 1121 ' return (-1);\n', 1122 ' {' ] 1123 code = TranslateList(code, self.GetTranslation()) 1124 1125 codearrayassign = self._entry.CodeArrayAssign( 1126 'msg->%(name)s_data[off]' % self.GetTranslation(), 'value') 1127 code += [' ' + x for x in codearrayassign] 1128 1129 code += TranslateList([ 1130 ' }', 1131 ' return (0);', 1132 '}' ], self.GetTranslation()) 1133 1134 return code 1135 1136 def CodeAdd(self): 1137 codearrayadd = self._entry.CodeArrayAdd( 1138 'msg->%(name)s_data[msg->%(name)s_length - 1]' % self.GetTranslation(), 1139 'value') 1140 code = [ 1141 'static int', 1142 '%(parent_name)s_%(name)s_expand_to_hold_more(' 1143 'struct %(parent_name)s *msg)', 1144 '{', 1145 ' int tobe_allocated = msg->%(name)s_num_allocated;', 1146 ' %(ctype)s* new_data = NULL;', 1147 ' tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;', 1148 ' new_data = (%(ctype)s*) realloc(msg->%(name)s_data,', 1149 ' tobe_allocated * sizeof(%(ctype)s));', 1150 ' if (new_data == NULL)', 1151 ' return -1;', 1152 ' msg->%(name)s_data = new_data;', 1153 ' msg->%(name)s_num_allocated = tobe_allocated;', 1154 ' return 0;' 1155 '}', 1156 '', 1157 '%(ctype)s %(optpointer)s', 1158 '%(parent_name)s_%(name)s_add(' 1159 'struct %(parent_name)s *msg%(optaddarg)s)', 1160 '{', 1161 ' if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {', 1162 ' if (%(parent_name)s_%(name)s_expand_to_hold_more(msg)<0)', 1163 ' goto error;', 1164 ' }' ] 1165 1166 code = TranslateList(code, self.GetTranslation()) 1167 1168 code += [' ' + x for x in codearrayadd] 1169 1170 code += TranslateList([ 1171 ' msg->%(name)s_set = 1;', 1172 ' return %(optreference)s(msg->%(name)s_data[' 1173 'msg->%(name)s_length - 1]);', 1174 'error:', 1175 ' --msg->%(name)s_length;', 1176 ' return (NULL);', 1177 '}' ], self.GetTranslation()) 1178 1179 return code 1180 1181 def CodeComplete(self, structname, var_name): 1182 self._index = 'i' 1183 tmp = self._entry.CodeComplete(structname, self._entry.GetVarName(var_name)) 1184 # skip the whole loop if there is nothing to check 1185 if not tmp: 1186 return [] 1187 1188 translate = self.GetTranslation({ 'structname' : structname }) 1189 code = [ 1190 '{', 1191 ' int i;', 1192 ' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ] 1193 1194 code = TranslateList(code, translate) 1195 1196 code += [' ' + x for x in tmp] 1197 1198 code += [ 1199 ' }', 1200 '}' ] 1201 1202 return code 1203 1204 def CodeUnmarshal(self, buf, tag_name, var_name, var_len): 1205 translate = self.GetTranslation({ 'var' : var_name, 1206 'buf' : buf, 1207 'tag' : tag_name, 1208 'init' : self._entry.GetInitializer()}) 1209 code = [ 1210 'if (%(var)s->%(name)s_length >= %(var)s->%(name)s_num_allocated &&', 1211 ' %(parent_name)s_%(name)s_expand_to_hold_more(%(var)s) < 0) {', 1212 ' puts("HEY NOW");', 1213 ' return (-1);', 1214 '}'] 1215 1216 # the unmarshal code directly returns 1217 code = TranslateList(code, translate) 1218 1219 self._index = '%(var)s->%(name)s_length' % translate 1220 code += self._entry.CodeUnmarshal(buf, tag_name, 1221 self._entry.GetVarName(var_name), 1222 self._entry.GetVarLen(var_name)) 1223 1224 code += [ '++%(var)s->%(name)s_length;' % translate ] 1225 1226 return code 1227 1228 def CodeMarshal(self, buf, tag_name, var_name, var_len): 1229 code = ['{', 1230 ' int i;', 1231 ' for (i = 0; i < %(var)s->%(name)s_length; ++i) {' ] 1232 1233 self._index = 'i' 1234 code += self._entry.CodeMarshal(buf, tag_name, 1235 self._entry.GetVarName(var_name), 1236 self._entry.GetVarLen(var_name)) 1237 code += [' }', 1238 '}' 1239 ] 1240 1241 code = "\n".join(code) % self.GetTranslation({ 'var' : var_name }) 1242 1243 return code.split('\n') 1244 1245 def CodeClear(self, structname): 1246 translate = self.GetTranslation({ 'structname' : structname }) 1247 codearrayfree = self._entry.CodeArrayFree( 1248 '%(structname)s->%(name)s_data[i]' % self.GetTranslation( 1249 { 'structname' : structname } )) 1250 1251 code = [ 'if (%(structname)s->%(name)s_set == 1) {' ] 1252 1253 if codearrayfree: 1254 code += [ 1255 ' int i;', 1256 ' for (i = 0; i < %(structname)s->%(name)s_length; ++i) {' ] 1257 1258 code = TranslateList(code, translate) 1259 1260 if codearrayfree: 1261 code += [' ' + x for x in codearrayfree] 1262 code += [ 1263 ' }' ] 1264 1265 code += TranslateList([ 1266 ' free(%(structname)s->%(name)s_data);', 1267 ' %(structname)s->%(name)s_data = NULL;', 1268 ' %(structname)s->%(name)s_set = 0;', 1269 ' %(structname)s->%(name)s_length = 0;', 1270 ' %(structname)s->%(name)s_num_allocated = 0;', 1271 '}' 1272 ], translate) 1273 1274 return code 1275 1276 def CodeInitialize(self, name): 1277 code = ['%s->%s_data = NULL;' % (name, self._name), 1278 '%s->%s_length = 0;' % (name, self._name), 1279 '%s->%s_num_allocated = 0;' % (name, self._name)] 1280 return code 1281 1282 def CodeFree(self, structname): 1283 code = self.CodeClear(structname); 1284 1285 code += TranslateList([ 1286 'free(%(structname)s->%(name)s_data);' ], 1287 self.GetTranslation({'structname' : structname })) 1288 1289 return code 1290 1291 def Declaration(self): 1292 dcl = ['%s *%s_data;' % (self._ctype, self._name), 1293 'int %s_length;' % self._name, 1294 'int %s_num_allocated;' % self._name ] 1295 1296 return dcl 1297 1298def NormalizeLine(line): 1299 global white 1300 global cppcomment 1301 1302 line = cppcomment.sub('', line) 1303 line = line.strip() 1304 line = white.sub(' ', line) 1305 1306 return line 1307 1308def ProcessOneEntry(factory, newstruct, entry): 1309 optional = 0 1310 array = 0 1311 entry_type = '' 1312 name = '' 1313 tag = '' 1314 tag_set = None 1315 separator = '' 1316 fixed_length = '' 1317 1318 tokens = entry.split(' ') 1319 while tokens: 1320 token = tokens[0] 1321 tokens = tokens[1:] 1322 1323 if not entry_type: 1324 if not optional and token == 'optional': 1325 optional = 1 1326 continue 1327 1328 if not array and token == 'array': 1329 array = 1 1330 continue 1331 1332 if not entry_type: 1333 entry_type = token 1334 continue 1335 1336 if not name: 1337 res = re.match(r'^([^\[\]]+)(\[.*\])?$', token) 1338 if not res: 1339 raise RpcGenError( 1340 'Cannot parse name: \"%s\" ' 1341 'around line %d' % (entry, line_count)) 1342 name = res.group(1) 1343 fixed_length = res.group(2) 1344 if fixed_length: 1345 fixed_length = fixed_length[1:-1] 1346 continue 1347 1348 if not separator: 1349 separator = token 1350 if separator != '=': 1351 raise RpcGenError('Expected "=" after name \"%s\" got %s' 1352 % (name, token)) 1353 continue 1354 1355 if not tag_set: 1356 tag_set = 1 1357 if not re.match(r'^(0x)?[0-9]+$', token): 1358 raise RpcGenError('Expected tag number: \"%s\"' % entry) 1359 tag = int(token, 0) 1360 continue 1361 1362 raise RpcGenError('Cannot parse \"%s\"' % entry) 1363 1364 if not tag_set: 1365 raise RpcGenError('Need tag number: \"%s\"' % entry) 1366 1367 # Create the right entry 1368 if entry_type == 'bytes': 1369 if fixed_length: 1370 newentry = factory.EntryBytes(entry_type, name, tag, fixed_length) 1371 else: 1372 newentry = factory.EntryVarBytes(entry_type, name, tag) 1373 elif entry_type == 'int' and not fixed_length: 1374 newentry = factory.EntryInt(entry_type, name, tag) 1375 elif entry_type == 'int64' and not fixed_length: 1376 newentry = factory.EntryInt(entry_type, name, tag, bits=64) 1377 elif entry_type == 'string' and not fixed_length: 1378 newentry = factory.EntryString(entry_type, name, tag) 1379 else: 1380 res = structref.match(entry_type) 1381 if res: 1382 # References another struct defined in our file 1383 newentry = factory.EntryStruct(entry_type, name, tag, res.group(1)) 1384 else: 1385 raise RpcGenError('Bad type: "%s" in "%s"' % (entry_type, entry)) 1386 1387 structs = [] 1388 1389 if optional: 1390 newentry.MakeOptional() 1391 if array: 1392 newentry.MakeArray() 1393 1394 newentry.SetStruct(newstruct) 1395 newentry.SetLineCount(line_count) 1396 newentry.Verify() 1397 1398 if array: 1399 # We need to encapsulate this entry into a struct 1400 newname = newentry.Name()+ '_array' 1401 1402 # Now borgify the new entry. 1403 newentry = factory.EntryArray(newentry) 1404 newentry.SetStruct(newstruct) 1405 newentry.SetLineCount(line_count) 1406 newentry.MakeArray() 1407 1408 newstruct.AddEntry(newentry) 1409 1410 return structs 1411 1412def ProcessStruct(factory, data): 1413 tokens = data.split(' ') 1414 1415 # First three tokens are: 'struct' 'name' '{' 1416 newstruct = factory.Struct(tokens[1]) 1417 1418 inside = ' '.join(tokens[3:-1]) 1419 1420 tokens = inside.split(';') 1421 1422 structs = [] 1423 1424 for entry in tokens: 1425 entry = NormalizeLine(entry) 1426 if not entry: 1427 continue 1428 1429 # It's possible that new structs get defined in here 1430 structs.extend(ProcessOneEntry(factory, newstruct, entry)) 1431 1432 structs.append(newstruct) 1433 return structs 1434 1435def GetNextStruct(file): 1436 global line_count 1437 global cppdirect 1438 1439 got_struct = 0 1440 1441 processed_lines = [] 1442 1443 have_c_comment = 0 1444 data = '' 1445 while 1: 1446 line = file.readline() 1447 if not line: 1448 break 1449 1450 line_count += 1 1451 line = line[:-1] 1452 1453 if not have_c_comment and re.search(r'/\*', line): 1454 if re.search(r'/\*.*?\*/', line): 1455 line = re.sub(r'/\*.*?\*/', '', line) 1456 else: 1457 line = re.sub(r'/\*.*$', '', line) 1458 have_c_comment = 1 1459 1460 if have_c_comment: 1461 if not re.search(r'\*/', line): 1462 continue 1463 have_c_comment = 0 1464 line = re.sub(r'^.*\*/', '', line) 1465 1466 line = NormalizeLine(line) 1467 1468 if not line: 1469 continue 1470 1471 if not got_struct: 1472 if re.match(r'#include ["<].*[>"]', line): 1473 cppdirect.append(line) 1474 continue 1475 1476 if re.match(r'^#(if( |def)|endif)', line): 1477 cppdirect.append(line) 1478 continue 1479 1480 if re.match(r'^#define', line): 1481 headerdirect.append(line) 1482 continue 1483 1484 if not structdef.match(line): 1485 raise RpcGenError('Missing struct on line %d: %s' 1486 % (line_count, line)) 1487 else: 1488 got_struct = 1 1489 data += line 1490 continue 1491 1492 # We are inside the struct 1493 tokens = line.split('}') 1494 if len(tokens) == 1: 1495 data += ' ' + line 1496 continue 1497 1498 if len(tokens[1]): 1499 raise RpcGenError('Trailing garbage after struct on line %d' 1500 % line_count) 1501 1502 # We found the end of the struct 1503 data += ' %s}' % tokens[0] 1504 break 1505 1506 # Remove any comments, that might be in there 1507 data = re.sub(r'/\*.*\*/', '', data) 1508 1509 return data 1510 1511 1512def Parse(factory, file): 1513 """ 1514 Parses the input file and returns C code and corresponding header file. 1515 """ 1516 1517 entities = [] 1518 1519 while 1: 1520 # Just gets the whole struct nicely formatted 1521 data = GetNextStruct(file) 1522 1523 if not data: 1524 break 1525 1526 entities.extend(ProcessStruct(factory, data)) 1527 1528 return entities 1529 1530class CCodeGenerator: 1531 def __init__(self): 1532 pass 1533 1534 def GuardName(self, name): 1535 # Use the complete provided path to the input file, with all 1536 # non-identifier characters replaced with underscores, to 1537 # reduce the chance of a collision between guard macros. 1538 return 'EVENT_RPCOUT_' + nonident.sub('_', name).upper() + '_' 1539 1540 def HeaderPreamble(self, name): 1541 guard = self.GuardName(name) 1542 pre = ( 1543 '/*\n' 1544 ' * Automatically generated from %s\n' 1545 ' */\n\n' 1546 '#ifndef %s\n' 1547 '#define %s\n\n' ) % ( 1548 name, guard, guard) 1549 1550 for statement in headerdirect: 1551 pre += '%s\n' % statement 1552 if headerdirect: 1553 pre += '\n' 1554 1555 pre += ( 1556 '#include <event2/util.h> /* for ev_uint*_t */\n' 1557 '#include <event2/rpc.h>\n' 1558 ) 1559 1560 return pre 1561 1562 def HeaderPostamble(self, name): 1563 guard = self.GuardName(name) 1564 return '#endif /* %s */' % guard 1565 1566 def BodyPreamble(self, name, header_file): 1567 global _NAME 1568 global _VERSION 1569 1570 slash = header_file.rfind('/') 1571 if slash != -1: 1572 header_file = header_file[slash+1:] 1573 1574 pre = ( '/*\n' 1575 ' * Automatically generated from %s\n' 1576 ' * by %s/%s. DO NOT EDIT THIS FILE.\n' 1577 ' */\n\n' ) % (name, _NAME, _VERSION) 1578 pre += ( '#include <stdlib.h>\n' 1579 '#include <string.h>\n' 1580 '#include <assert.h>\n' 1581 '#include <event2/event-config.h>\n' 1582 '#include <event2/event.h>\n' 1583 '#include <event2/buffer.h>\n' 1584 '#include <event2/tag.h>\n\n' 1585 '#if defined(EVENT__HAVE___func__)\n' 1586 '# ifndef __func__\n' 1587 '# define __func__ __func__\n' 1588 '# endif\n' 1589 '#elif defined(EVENT__HAVE___FUNCTION__)\n' 1590 '# define __func__ __FUNCTION__\n' 1591 '#else\n' 1592 '# define __func__ __FILE__\n' 1593 '#endif\n\n' 1594 ) 1595 1596 for statement in cppdirect: 1597 pre += '%s\n' % statement 1598 1599 pre += '\n#include "%s"\n\n' % header_file 1600 1601 pre += 'void event_warn(const char *fmt, ...);\n' 1602 pre += 'void event_warnx(const char *fmt, ...);\n\n' 1603 1604 return pre 1605 1606 def HeaderFilename(self, filename): 1607 return '.'.join(filename.split('.')[:-1]) + '.h' 1608 1609 def CodeFilename(self, filename): 1610 return '.'.join(filename.split('.')[:-1]) + '.gen.c' 1611 1612 def Struct(self, name): 1613 return StructCCode(name) 1614 1615 def EntryBytes(self, entry_type, name, tag, fixed_length): 1616 return EntryBytes(entry_type, name, tag, fixed_length) 1617 1618 def EntryVarBytes(self, entry_type, name, tag): 1619 return EntryVarBytes(entry_type, name, tag) 1620 1621 def EntryInt(self, entry_type, name, tag, bits=32): 1622 return EntryInt(entry_type, name, tag, bits) 1623 1624 def EntryString(self, entry_type, name, tag): 1625 return EntryString(entry_type, name, tag) 1626 1627 def EntryStruct(self, entry_type, name, tag, struct_name): 1628 return EntryStruct(entry_type, name, tag, struct_name) 1629 1630 def EntryArray(self, entry): 1631 return EntryArray(entry) 1632 1633class Usage(RpcGenError): 1634 def __init__(self, argv0): 1635 RpcGenError.__init__("usage: %s input.rpc [[output.h] output.c]" 1636 % argv0) 1637 1638class CommandLine: 1639 def __init__(self, argv): 1640 """Initialize a command-line to launch event_rpcgen, as if 1641 from a command-line with CommandLine(sys.argv). If you're 1642 calling this directly, remember to provide a dummy value 1643 for sys.argv[0] 1644 """ 1645 self.filename = None 1646 self.header_file = None 1647 self.impl_file = None 1648 self.factory = CCodeGenerator() 1649 1650 if len(argv) >= 2 and argv[1] == '--quiet': 1651 global QUIETLY 1652 QUIETLY = 1 1653 del argv[1] 1654 1655 if len(argv) < 2 or len(argv) > 4: 1656 raise Usage(argv[0]) 1657 1658 self.filename = argv[1].replace('\\', '/') 1659 if len(argv) == 3: 1660 self.impl_file = argv[2].replace('\\', '/') 1661 if len(argv) == 4: 1662 self.header_file = argv[2].replace('\\', '/') 1663 self.impl_file = argv[3].replace('\\', '/') 1664 1665 if not self.filename: 1666 raise Usage(argv[0]) 1667 1668 if not self.impl_file: 1669 self.impl_file = self.factory.CodeFilename(self.filename) 1670 1671 if not self.header_file: 1672 self.header_file = self.factory.HeaderFilename(self.impl_file) 1673 1674 if not self.impl_file.endswith('.c'): 1675 raise RpcGenError("can only generate C implementation files") 1676 if not self.header_file.endswith('.h'): 1677 raise RpcGenError("can only generate C header files") 1678 1679 def run(self): 1680 filename = self.filename 1681 header_file = self.header_file 1682 impl_file = self.impl_file 1683 factory = self.factory 1684 1685 declare('Reading \"%s\"' % filename) 1686 1687 fp = open(filename, 'r') 1688 entities = Parse(factory, fp) 1689 fp.close() 1690 1691 declare('... creating "%s"' % header_file) 1692 header_fp = open(header_file, 'w') 1693 header_fp.write(factory.HeaderPreamble(filename)) 1694 1695 # Create forward declarations: allows other structs to reference 1696 # each other 1697 for entry in entities: 1698 entry.PrintForwardDeclaration(header_fp) 1699 header_fp.write('\n') 1700 1701 for entry in entities: 1702 entry.PrintTags(header_fp) 1703 entry.PrintDeclaration(header_fp) 1704 header_fp.write(factory.HeaderPostamble(filename)) 1705 header_fp.close() 1706 1707 declare('... creating "%s"' % impl_file) 1708 impl_fp = open(impl_file, 'w') 1709 impl_fp.write(factory.BodyPreamble(filename, header_file)) 1710 for entry in entities: 1711 entry.PrintCode(impl_fp) 1712 impl_fp.close() 1713 1714if __name__ == '__main__': 1715 try: 1716 CommandLine(sys.argv).run() 1717 sys.exit(0) 1718 1719 except RpcGenError as e: 1720 sys.stderr.write(e) 1721 sys.exit(1) 1722 1723 except EnvironmentError as e: 1724 if e.filename and e.strerror: 1725 sys.stderr.write("%s: %s" % (e.filename, e.strerror)) 1726 sys.exit(1) 1727 elif e.strerror: 1728 sys.stderr.write(e.strerror) 1729 sys.exit(1) 1730 else: 1731 raise 1732