Annotation of embedaddon/libevent/event_rpcgen.py, revision 1.1
1.1 ! misho 1: #!/usr/bin/env python
! 2: #
! 3: # Copyright (c) 2005 Niels Provos <provos@citi.umich.edu>
! 4: # All rights reserved.
! 5: #
! 6: # Generates marshaling code based on libevent.
! 7:
! 8: import sys
! 9: import re
! 10:
! 11: #
! 12: _NAME = "event_rpcgen.py"
! 13: _VERSION = "0.1"
! 14: _STRUCT_RE = '[a-z][a-z_0-9]*'
! 15:
! 16: # Globals
! 17: line_count = 0
! 18:
! 19: white = re.compile(r'^\s+')
! 20: cppcomment = re.compile(r'\/\/.*$')
! 21: headerdirect = []
! 22: cppdirect = []
! 23:
! 24: # Holds everything that makes a struct
! 25: class Struct:
! 26: def __init__(self, name):
! 27: self._name = name
! 28: self._entries = []
! 29: self._tags = {}
! 30: print >>sys.stderr, ' Created struct: %s' % name
! 31:
! 32: def AddEntry(self, entry):
! 33: if self._tags.has_key(entry.Tag()):
! 34: print >>sys.stderr, ( 'Entry "%s" duplicates tag number '
! 35: '%d from "%s" around line %d' ) % (
! 36: entry.Name(), entry.Tag(),
! 37: self._tags[entry.Tag()], line_count)
! 38: sys.exit(1)
! 39: self._entries.append(entry)
! 40: self._tags[entry.Tag()] = entry.Name()
! 41: print >>sys.stderr, ' Added entry: %s' % entry.Name()
! 42:
! 43: def Name(self):
! 44: return self._name
! 45:
! 46: def EntryTagName(self, entry):
! 47: """Creates the name inside an enumeration for distinguishing data
! 48: types."""
! 49: name = "%s_%s" % (self._name, entry.Name())
! 50: return name.upper()
! 51:
! 52: def PrintIdented(self, file, ident, code):
! 53: """Takes an array, add indentation to each entry and prints it."""
! 54: for entry in code:
! 55: print >>file, '%s%s' % (ident, entry)
! 56:
! 57: def PrintTags(self, file):
! 58: """Prints the tag definitions for a structure."""
! 59: print >>file, '/* Tag definition for %s */' % self._name
! 60: print >>file, 'enum %s_ {' % self._name.lower()
! 61: for entry in self._entries:
! 62: print >>file, ' %s=%d,' % (self.EntryTagName(entry),
! 63: entry.Tag())
! 64: print >>file, ' %s_MAX_TAGS' % (self._name.upper())
! 65: print >>file, '};\n'
! 66:
! 67: def PrintForwardDeclaration(self, file):
! 68: print >>file, 'struct %s;' % self._name
! 69:
! 70: def PrintDeclaration(self, file):
! 71: print >>file, '/* Structure declaration for %s */' % self._name
! 72: print >>file, 'struct %s_access_ {' % self._name
! 73: for entry in self._entries:
! 74: dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name())
! 75: dcl.extend(
! 76: entry.GetDeclaration('(*%s_get)' % entry.Name()))
! 77: if entry.Array():
! 78: dcl.extend(
! 79: entry.AddDeclaration('(*%s_add)' % entry.Name()))
! 80: self.PrintIdented(file, ' ', dcl)
! 81: print >>file, '};\n'
! 82:
! 83: print >>file, 'struct %s {' % self._name
! 84: print >>file, ' struct %s_access_ *base;\n' % self._name
! 85: for entry in self._entries:
! 86: dcl = entry.Declaration()
! 87: self.PrintIdented(file, ' ', dcl)
! 88: print >>file, ''
! 89: for entry in self._entries:
! 90: print >>file, ' ev_uint8_t %s_set;' % entry.Name()
! 91: print >>file, '};\n'
! 92:
! 93: print >>file, \
! 94: """struct %(name)s *%(name)s_new(void);
! 95: void %(name)s_free(struct %(name)s *);
! 96: void %(name)s_clear(struct %(name)s *);
! 97: void %(name)s_marshal(struct evbuffer *, const struct %(name)s *);
! 98: int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *);
! 99: int %(name)s_complete(struct %(name)s *);
! 100: void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t,
! 101: const struct %(name)s *);
! 102: int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
! 103: struct %(name)s *);""" % { 'name' : self._name }
! 104:
! 105:
! 106: # Write a setting function of every variable
! 107: for entry in self._entries:
! 108: self.PrintIdented(file, '', entry.AssignDeclaration(
! 109: entry.AssignFuncName()))
! 110: self.PrintIdented(file, '', entry.GetDeclaration(
! 111: entry.GetFuncName()))
! 112: if entry.Array():
! 113: self.PrintIdented(file, '', entry.AddDeclaration(
! 114: entry.AddFuncName()))
! 115:
! 116: print >>file, '/* --- %s done --- */\n' % self._name
! 117:
! 118: def PrintCode(self, file):
! 119: print >>file, ('/*\n'
! 120: ' * Implementation of %s\n'
! 121: ' */\n') % self._name
! 122:
! 123: print >>file, \
! 124: 'static struct %(name)s_access_ __%(name)s_base = {' % \
! 125: { 'name' : self._name }
! 126: for entry in self._entries:
! 127: self.PrintIdented(file, ' ', entry.CodeBase())
! 128: print >>file, '};\n'
! 129:
! 130: # Creation
! 131: print >>file, (
! 132: 'struct %(name)s *\n'
! 133: '%(name)s_new(void)\n'
! 134: '{\n'
! 135: ' struct %(name)s *tmp;\n'
! 136: ' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n'
! 137: ' event_warn("%%s: malloc", __func__);\n'
! 138: ' return (NULL);\n'
! 139: ' }\n'
! 140: ' tmp->base = &__%(name)s_base;\n') % { 'name' : self._name }
! 141:
! 142: for entry in self._entries:
! 143: self.PrintIdented(file, ' ', entry.CodeNew('tmp'))
! 144: print >>file, ' tmp->%s_set = 0;\n' % entry.Name()
! 145:
! 146: print >>file, (
! 147: ' return (tmp);\n'
! 148: '}\n')
! 149:
! 150: # Adding
! 151: for entry in self._entries:
! 152: if entry.Array():
! 153: self.PrintIdented(file, '', entry.CodeAdd())
! 154: print >>file, ''
! 155:
! 156: # Assigning
! 157: for entry in self._entries:
! 158: self.PrintIdented(file, '', entry.CodeAssign())
! 159: print >>file, ''
! 160:
! 161: # Getting
! 162: for entry in self._entries:
! 163: self.PrintIdented(file, '', entry.CodeGet())
! 164: print >>file, ''
! 165:
! 166: # Clearing
! 167: print >>file, ( 'void\n'
! 168: '%(name)s_clear(struct %(name)s *tmp)\n'
! 169: '{'
! 170: ) % { 'name' : self._name }
! 171: for entry in self._entries:
! 172: self.PrintIdented(file, ' ', entry.CodeClear('tmp'))
! 173:
! 174: print >>file, '}\n'
! 175:
! 176: # Freeing
! 177: print >>file, ( 'void\n'
! 178: '%(name)s_free(struct %(name)s *tmp)\n'
! 179: '{'
! 180: ) % { 'name' : self._name }
! 181:
! 182: for entry in self._entries:
! 183: self.PrintIdented(file, ' ', entry.CodeFree('tmp'))
! 184:
! 185: print >>file, (' free(tmp);\n'
! 186: '}\n')
! 187:
! 188: # Marshaling
! 189: print >>file, ('void\n'
! 190: '%(name)s_marshal(struct evbuffer *evbuf, '
! 191: 'const struct %(name)s *tmp)'
! 192: '{') % { 'name' : self._name }
! 193: for entry in self._entries:
! 194: indent = ' '
! 195: # Optional entries do not have to be set
! 196: if entry.Optional():
! 197: indent += ' '
! 198: print >>file, ' if (tmp->%s_set) {' % entry.Name()
! 199: self.PrintIdented(
! 200: file, indent,
! 201: entry.CodeMarshal('evbuf', self.EntryTagName(entry), 'tmp'))
! 202: if entry.Optional():
! 203: print >>file, ' }'
! 204:
! 205: print >>file, '}\n'
! 206:
! 207: # Unmarshaling
! 208: print >>file, ('int\n'
! 209: '%(name)s_unmarshal(struct %(name)s *tmp, '
! 210: ' struct evbuffer *evbuf)\n'
! 211: '{\n'
! 212: ' ev_uint32_t tag;\n'
! 213: ' while (EVBUFFER_LENGTH(evbuf) > 0) {\n'
! 214: ' if (evtag_peek(evbuf, &tag) == -1)\n'
! 215: ' return (-1);\n'
! 216: ' switch (tag) {\n'
! 217: ) % { 'name' : self._name }
! 218: for entry in self._entries:
! 219: print >>file, ' case %s:\n' % self.EntryTagName(entry)
! 220: if not entry.Array():
! 221: print >>file, (
! 222: ' if (tmp->%s_set)\n'
! 223: ' return (-1);'
! 224: ) % (entry.Name())
! 225:
! 226: self.PrintIdented(
! 227: file, ' ',
! 228: entry.CodeUnmarshal('evbuf',
! 229: self.EntryTagName(entry), 'tmp'))
! 230:
! 231: print >>file, ( ' tmp->%s_set = 1;\n' % entry.Name() +
! 232: ' break;\n' )
! 233: print >>file, ( ' default:\n'
! 234: ' return -1;\n'
! 235: ' }\n'
! 236: ' }\n' )
! 237: # Check if it was decoded completely
! 238: print >>file, ( ' if (%(name)s_complete(tmp) == -1)\n'
! 239: ' return (-1);'
! 240: ) % { 'name' : self._name }
! 241:
! 242: # Successfully decoded
! 243: print >>file, ( ' return (0);\n'
! 244: '}\n')
! 245:
! 246: # Checking if a structure has all the required data
! 247: print >>file, (
! 248: 'int\n'
! 249: '%(name)s_complete(struct %(name)s *msg)\n'
! 250: '{' ) % { 'name' : self._name }
! 251: for entry in self._entries:
! 252: self.PrintIdented(
! 253: file, ' ',
! 254: entry.CodeComplete('msg'))
! 255: print >>file, (
! 256: ' return (0);\n'
! 257: '}\n' )
! 258:
! 259: # Complete message unmarshaling
! 260: print >>file, (
! 261: 'int\n'
! 262: 'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, '
! 263: 'ev_uint32_t need_tag, struct %(name)s *msg)\n'
! 264: '{\n'
! 265: ' ev_uint32_t tag;\n'
! 266: ' int res = -1;\n'
! 267: '\n'
! 268: ' struct evbuffer *tmp = evbuffer_new();\n'
! 269: '\n'
! 270: ' if (evtag_unmarshal(evbuf, &tag, tmp) == -1'
! 271: ' || tag != need_tag)\n'
! 272: ' goto error;\n'
! 273: '\n'
! 274: ' if (%(name)s_unmarshal(msg, tmp) == -1)\n'
! 275: ' goto error;\n'
! 276: '\n'
! 277: ' res = 0;\n'
! 278: '\n'
! 279: ' error:\n'
! 280: ' evbuffer_free(tmp);\n'
! 281: ' return (res);\n'
! 282: '}\n' ) % { 'name' : self._name }
! 283:
! 284: # Complete message marshaling
! 285: print >>file, (
! 286: 'void\n'
! 287: 'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, '
! 288: 'const struct %(name)s *msg)\n'
! 289: '{\n'
! 290: ' struct evbuffer *_buf = evbuffer_new();\n'
! 291: ' assert(_buf != NULL);\n'
! 292: ' evbuffer_drain(_buf, -1);\n'
! 293: ' %(name)s_marshal(_buf, msg);\n'
! 294: ' evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf), '
! 295: 'EVBUFFER_LENGTH(_buf));\n'
! 296: ' evbuffer_free(_buf);\n'
! 297: '}\n' ) % { 'name' : self._name }
! 298:
! 299: class Entry:
! 300: def __init__(self, type, name, tag):
! 301: self._type = type
! 302: self._name = name
! 303: self._tag = int(tag)
! 304: self._ctype = type
! 305: self._optional = 0
! 306: self._can_be_array = 0
! 307: self._array = 0
! 308: self._line_count = -1
! 309: self._struct = None
! 310: self._refname = None
! 311:
! 312: def GetTranslation(self):
! 313: return { "parent_name" : self._struct.Name(),
! 314: "name" : self._name,
! 315: "ctype" : self._ctype,
! 316: "refname" : self._refname
! 317: }
! 318:
! 319: def SetStruct(self, struct):
! 320: self._struct = struct
! 321:
! 322: def LineCount(self):
! 323: assert self._line_count != -1
! 324: return self._line_count
! 325:
! 326: def SetLineCount(self, number):
! 327: self._line_count = number
! 328:
! 329: def Array(self):
! 330: return self._array
! 331:
! 332: def Optional(self):
! 333: return self._optional
! 334:
! 335: def Tag(self):
! 336: return self._tag
! 337:
! 338: def Name(self):
! 339: return self._name
! 340:
! 341: def Type(self):
! 342: return self._type
! 343:
! 344: def MakeArray(self, yes=1):
! 345: self._array = yes
! 346:
! 347: def MakeOptional(self):
! 348: self._optional = 1
! 349:
! 350: def GetFuncName(self):
! 351: return '%s_%s_get' % (self._struct.Name(), self._name)
! 352:
! 353: def GetDeclaration(self, funcname):
! 354: code = [ 'int %s(struct %s *, %s *);' % (
! 355: funcname, self._struct.Name(), self._ctype ) ]
! 356: return code
! 357:
! 358: def CodeGet(self):
! 359: code = (
! 360: 'int',
! 361: '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, '
! 362: '%(ctype)s *value)',
! 363: '{',
! 364: ' if (msg->%(name)s_set != 1)',
! 365: ' return (-1);',
! 366: ' *value = msg->%(name)s_data;',
! 367: ' return (0);',
! 368: '}' )
! 369: code = '\n'.join(code)
! 370: code = code % self.GetTranslation()
! 371: return code.split('\n')
! 372:
! 373: def AssignFuncName(self):
! 374: return '%s_%s_assign' % (self._struct.Name(), self._name)
! 375:
! 376: def AddFuncName(self):
! 377: return '%s_%s_add' % (self._struct.Name(), self._name)
! 378:
! 379: def AssignDeclaration(self, funcname):
! 380: code = [ 'int %s(struct %s *, const %s);' % (
! 381: funcname, self._struct.Name(), self._ctype ) ]
! 382: return code
! 383:
! 384: def CodeAssign(self):
! 385: code = [ 'int',
! 386: '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,'
! 387: ' const %(ctype)s value)',
! 388: '{',
! 389: ' msg->%(name)s_set = 1;',
! 390: ' msg->%(name)s_data = value;',
! 391: ' return (0);',
! 392: '}' ]
! 393: code = '\n'.join(code)
! 394: code = code % self.GetTranslation()
! 395: return code.split('\n')
! 396:
! 397: def CodeClear(self, structname):
! 398: code = [ '%s->%s_set = 0;' % (structname, self.Name()) ]
! 399:
! 400: return code
! 401:
! 402: def CodeComplete(self, structname):
! 403: if self.Optional():
! 404: return []
! 405:
! 406: code = [ 'if (!%s->%s_set)' % (structname, self.Name()),
! 407: ' return (-1);' ]
! 408:
! 409: return code
! 410:
! 411: def CodeFree(self, name):
! 412: return []
! 413:
! 414: def CodeBase(self):
! 415: code = [
! 416: '%(parent_name)s_%(name)s_assign,',
! 417: '%(parent_name)s_%(name)s_get,'
! 418: ]
! 419: if self.Array():
! 420: code.append('%(parent_name)s_%(name)s_add,')
! 421:
! 422: code = '\n'.join(code)
! 423: code = code % self.GetTranslation()
! 424: return code.split('\n')
! 425:
! 426: def Verify(self):
! 427: if self.Array() and not self._can_be_array:
! 428: print >>sys.stderr, (
! 429: 'Entry "%s" cannot be created as an array '
! 430: 'around line %d' ) % (self._name, self.LineCount())
! 431: sys.exit(1)
! 432: if not self._struct:
! 433: print >>sys.stderr, (
! 434: 'Entry "%s" does not know which struct it belongs to '
! 435: 'around line %d' ) % (self._name, self.LineCount())
! 436: sys.exit(1)
! 437: if self._optional and self._array:
! 438: print >>sys.stderr, ( 'Entry "%s" has illegal combination of '
! 439: 'optional and array around line %d' ) % (
! 440: self._name, self.LineCount() )
! 441: sys.exit(1)
! 442:
! 443: class EntryBytes(Entry):
! 444: def __init__(self, type, name, tag, length):
! 445: # Init base class
! 446: Entry.__init__(self, type, name, tag)
! 447:
! 448: self._length = length
! 449: self._ctype = 'ev_uint8_t'
! 450:
! 451: def GetDeclaration(self, funcname):
! 452: code = [ 'int %s(struct %s *, %s **);' % (
! 453: funcname, self._struct.Name(), self._ctype ) ]
! 454: return code
! 455:
! 456: def AssignDeclaration(self, funcname):
! 457: code = [ 'int %s(struct %s *, const %s *);' % (
! 458: funcname, self._struct.Name(), self._ctype ) ]
! 459: return code
! 460:
! 461: def Declaration(self):
! 462: dcl = ['ev_uint8_t %s_data[%s];' % (self._name, self._length)]
! 463:
! 464: return dcl
! 465:
! 466: def CodeGet(self):
! 467: name = self._name
! 468: code = [ 'int',
! 469: '%s_%s_get(struct %s *msg, %s **value)' % (
! 470: self._struct.Name(), name,
! 471: self._struct.Name(), self._ctype),
! 472: '{',
! 473: ' if (msg->%s_set != 1)' % name,
! 474: ' return (-1);',
! 475: ' *value = msg->%s_data;' % name,
! 476: ' return (0);',
! 477: '}' ]
! 478: return code
! 479:
! 480: def CodeAssign(self):
! 481: name = self._name
! 482: code = [ 'int',
! 483: '%s_%s_assign(struct %s *msg, const %s *value)' % (
! 484: self._struct.Name(), name,
! 485: self._struct.Name(), self._ctype),
! 486: '{',
! 487: ' msg->%s_set = 1;' % name,
! 488: ' memcpy(msg->%s_data, value, %s);' % (
! 489: name, self._length),
! 490: ' return (0);',
! 491: '}' ]
! 492: return code
! 493:
! 494: def CodeUnmarshal(self, buf, tag_name, var_name):
! 495: code = [ 'if (evtag_unmarshal_fixed(%s, %s, ' % (buf, tag_name) +
! 496: '%s->%s_data, ' % (var_name, self._name) +
! 497: 'sizeof(%s->%s_data)) == -1) {' % (
! 498: var_name, self._name),
! 499: ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
! 500: self._name ),
! 501: ' return (-1);',
! 502: '}'
! 503: ]
! 504: return code
! 505:
! 506: def CodeMarshal(self, buf, tag_name, var_name):
! 507: code = ['evtag_marshal(%s, %s, %s->%s_data, sizeof(%s->%s_data));' % (
! 508: buf, tag_name, var_name, self._name, var_name, self._name )]
! 509: return code
! 510:
! 511: def CodeClear(self, structname):
! 512: code = [ '%s->%s_set = 0;' % (structname, self.Name()),
! 513: 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
! 514: structname, self._name, structname, self._name)]
! 515:
! 516: return code
! 517:
! 518: def CodeNew(self, name):
! 519: code = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % (
! 520: name, self._name, name, self._name)]
! 521: return code
! 522:
! 523: def Verify(self):
! 524: if not self._length:
! 525: print >>sys.stderr, 'Entry "%s" needs a length around line %d' % (
! 526: self._name, self.LineCount() )
! 527: sys.exit(1)
! 528:
! 529: Entry.Verify(self)
! 530:
! 531: class EntryInt(Entry):
! 532: def __init__(self, type, name, tag):
! 533: # Init base class
! 534: Entry.__init__(self, type, name, tag)
! 535:
! 536: self._ctype = 'ev_uint32_t'
! 537:
! 538: def CodeUnmarshal(self, buf, tag_name, var_name):
! 539: code = ['if (evtag_unmarshal_int(%s, %s, &%s->%s_data) == -1) {' % (
! 540: buf, tag_name, var_name, self._name),
! 541: ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
! 542: self._name ),
! 543: ' return (-1);',
! 544: '}' ]
! 545: return code
! 546:
! 547: def CodeMarshal(self, buf, tag_name, var_name):
! 548: code = ['evtag_marshal_int(%s, %s, %s->%s_data);' % (
! 549: buf, tag_name, var_name, self._name)]
! 550: return code
! 551:
! 552: def Declaration(self):
! 553: dcl = ['ev_uint32_t %s_data;' % self._name]
! 554:
! 555: return dcl
! 556:
! 557: def CodeNew(self, name):
! 558: code = ['%s->%s_data = 0;' % (name, self._name)]
! 559: return code
! 560:
! 561: class EntryString(Entry):
! 562: def __init__(self, type, name, tag):
! 563: # Init base class
! 564: Entry.__init__(self, type, name, tag)
! 565:
! 566: self._ctype = 'char *'
! 567:
! 568: def CodeAssign(self):
! 569: name = self._name
! 570: code = """int
! 571: %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
! 572: const %(ctype)s value)
! 573: {
! 574: if (msg->%(name)s_data != NULL)
! 575: free(msg->%(name)s_data);
! 576: if ((msg->%(name)s_data = strdup(value)) == NULL)
! 577: return (-1);
! 578: msg->%(name)s_set = 1;
! 579: return (0);
! 580: }""" % self.GetTranslation()
! 581:
! 582: return code.split('\n')
! 583:
! 584: def CodeUnmarshal(self, buf, tag_name, var_name):
! 585: code = ['if (evtag_unmarshal_string(%s, %s, &%s->%s_data) == -1) {' % (
! 586: buf, tag_name, var_name, self._name),
! 587: ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
! 588: self._name ),
! 589: ' return (-1);',
! 590: '}'
! 591: ]
! 592: return code
! 593:
! 594: def CodeMarshal(self, buf, tag_name, var_name):
! 595: code = ['evtag_marshal_string(%s, %s, %s->%s_data);' % (
! 596: buf, tag_name, var_name, self._name)]
! 597: return code
! 598:
! 599: def CodeClear(self, structname):
! 600: code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
! 601: ' free (%s->%s_data);' % (structname, self.Name()),
! 602: ' %s->%s_data = NULL;' % (structname, self.Name()),
! 603: ' %s->%s_set = 0;' % (structname, self.Name()),
! 604: '}'
! 605: ]
! 606:
! 607: return code
! 608:
! 609: def CodeNew(self, name):
! 610: code = ['%s->%s_data = NULL;' % (name, self._name)]
! 611: return code
! 612:
! 613: def CodeFree(self, name):
! 614: code = ['if (%s->%s_data != NULL)' % (name, self._name),
! 615: ' free (%s->%s_data); ' % (name, self._name)]
! 616:
! 617: return code
! 618:
! 619: def Declaration(self):
! 620: dcl = ['char *%s_data;' % self._name]
! 621:
! 622: return dcl
! 623:
! 624: class EntryStruct(Entry):
! 625: def __init__(self, type, name, tag, refname):
! 626: # Init base class
! 627: Entry.__init__(self, type, name, tag)
! 628:
! 629: self._can_be_array = 1
! 630: self._refname = refname
! 631: self._ctype = 'struct %s*' % refname
! 632:
! 633: def CodeGet(self):
! 634: name = self._name
! 635: code = [ 'int',
! 636: '%s_%s_get(struct %s *msg, %s *value)' % (
! 637: self._struct.Name(), name,
! 638: self._struct.Name(), self._ctype),
! 639: '{',
! 640: ' if (msg->%s_set != 1) {' % name,
! 641: ' msg->%s_data = %s_new();' % (name, self._refname),
! 642: ' if (msg->%s_data == NULL)' % name,
! 643: ' return (-1);',
! 644: ' msg->%s_set = 1;' % name,
! 645: ' }',
! 646: ' *value = msg->%s_data;' % name,
! 647: ' return (0);',
! 648: '}' ]
! 649: return code
! 650:
! 651: def CodeAssign(self):
! 652: name = self._name
! 653: code = """int
! 654: %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,
! 655: const %(ctype)s value)
! 656: {
! 657: struct evbuffer *tmp = NULL;
! 658: if (msg->%(name)s_set) {
! 659: %(refname)s_clear(msg->%(name)s_data);
! 660: msg->%(name)s_set = 0;
! 661: } else {
! 662: msg->%(name)s_data = %(refname)s_new();
! 663: if (msg->%(name)s_data == NULL) {
! 664: event_warn("%%s: %(refname)s_new()", __func__);
! 665: goto error;
! 666: }
! 667: }
! 668: if ((tmp = evbuffer_new()) == NULL) {
! 669: event_warn("%%s: evbuffer_new()", __func__);
! 670: goto error;
! 671: }
! 672: %(refname)s_marshal(tmp, value);
! 673: if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) {
! 674: event_warnx("%%s: %(refname)s_unmarshal", __func__);
! 675: goto error;
! 676: }
! 677: msg->%(name)s_set = 1;
! 678: evbuffer_free(tmp);
! 679: return (0);
! 680: error:
! 681: if (tmp != NULL)
! 682: evbuffer_free(tmp);
! 683: if (msg->%(name)s_data != NULL) {
! 684: %(refname)s_free(msg->%(name)s_data);
! 685: msg->%(name)s_data = NULL;
! 686: }
! 687: return (-1);
! 688: }""" % self.GetTranslation()
! 689: return code.split('\n')
! 690:
! 691: def CodeComplete(self, structname):
! 692: if self.Optional():
! 693: code = [ 'if (%s->%s_set && %s_complete(%s->%s_data) == -1)' % (
! 694: structname, self.Name(),
! 695: self._refname, structname, self.Name()),
! 696: ' return (-1);' ]
! 697: else:
! 698: code = [ 'if (%s_complete(%s->%s_data) == -1)' % (
! 699: self._refname, structname, self.Name()),
! 700: ' return (-1);' ]
! 701:
! 702: return code
! 703:
! 704: def CodeUnmarshal(self, buf, tag_name, var_name):
! 705: code = ['%s->%s_data = %s_new();' % (
! 706: var_name, self._name, self._refname),
! 707: 'if (%s->%s_data == NULL)' % (var_name, self._name),
! 708: ' return (-1);',
! 709: 'if (evtag_unmarshal_%s(%s, %s, %s->%s_data) == -1) {' % (
! 710: self._refname, buf, tag_name, var_name, self._name),
! 711: ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
! 712: self._name ),
! 713: ' return (-1);',
! 714: '}'
! 715: ]
! 716: return code
! 717:
! 718: def CodeMarshal(self, buf, tag_name, var_name):
! 719: code = ['evtag_marshal_%s(%s, %s, %s->%s_data);' % (
! 720: self._refname, buf, tag_name, var_name, self._name)]
! 721: return code
! 722:
! 723: def CodeClear(self, structname):
! 724: code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
! 725: ' %s_free(%s->%s_data);' % (
! 726: self._refname, structname, self.Name()),
! 727: ' %s->%s_data = NULL;' % (structname, self.Name()),
! 728: ' %s->%s_set = 0;' % (structname, self.Name()),
! 729: '}'
! 730: ]
! 731:
! 732: return code
! 733:
! 734: def CodeNew(self, name):
! 735: code = ['%s->%s_data = NULL;' % (name, self._name)]
! 736: return code
! 737:
! 738: def CodeFree(self, name):
! 739: code = ['if (%s->%s_data != NULL)' % (name, self._name),
! 740: ' %s_free(%s->%s_data); ' % (
! 741: self._refname, name, self._name)]
! 742:
! 743: return code
! 744:
! 745: def Declaration(self):
! 746: dcl = ['%s %s_data;' % (self._ctype, self._name)]
! 747:
! 748: return dcl
! 749:
! 750: class EntryVarBytes(Entry):
! 751: def __init__(self, type, name, tag):
! 752: # Init base class
! 753: Entry.__init__(self, type, name, tag)
! 754:
! 755: self._ctype = 'ev_uint8_t *'
! 756:
! 757: def GetDeclaration(self, funcname):
! 758: code = [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % (
! 759: funcname, self._struct.Name(), self._ctype ) ]
! 760: return code
! 761:
! 762: def AssignDeclaration(self, funcname):
! 763: code = [ 'int %s(struct %s *, const %s, ev_uint32_t);' % (
! 764: funcname, self._struct.Name(), self._ctype ) ]
! 765: return code
! 766:
! 767: def CodeAssign(self):
! 768: name = self._name
! 769: code = [ 'int',
! 770: '%s_%s_assign(struct %s *msg, '
! 771: 'const %s value, ev_uint32_t len)' % (
! 772: self._struct.Name(), name,
! 773: self._struct.Name(), self._ctype),
! 774: '{',
! 775: ' if (msg->%s_data != NULL)' % name,
! 776: ' free (msg->%s_data);' % name,
! 777: ' msg->%s_data = malloc(len);' % name,
! 778: ' if (msg->%s_data == NULL)' % name,
! 779: ' return (-1);',
! 780: ' msg->%s_set = 1;' % name,
! 781: ' msg->%s_length = len;' % name,
! 782: ' memcpy(msg->%s_data, value, len);' % name,
! 783: ' return (0);',
! 784: '}' ]
! 785: return code
! 786:
! 787: def CodeGet(self):
! 788: name = self._name
! 789: code = [ 'int',
! 790: '%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)' % (
! 791: self._struct.Name(), name,
! 792: self._struct.Name(), self._ctype),
! 793: '{',
! 794: ' if (msg->%s_set != 1)' % name,
! 795: ' return (-1);',
! 796: ' *value = msg->%s_data;' % name,
! 797: ' *plen = msg->%s_length;' % name,
! 798: ' return (0);',
! 799: '}' ]
! 800: return code
! 801:
! 802: def CodeUnmarshal(self, buf, tag_name, var_name):
! 803: code = ['if (evtag_payload_length(%s, &%s->%s_length) == -1)' % (
! 804: buf, var_name, self._name),
! 805: ' return (-1);',
! 806: # We do not want DoS opportunities
! 807: 'if (%s->%s_length > EVBUFFER_LENGTH(%s))' % (
! 808: var_name, self._name, buf),
! 809: ' return (-1);',
! 810: 'if ((%s->%s_data = malloc(%s->%s_length)) == NULL)' % (
! 811: var_name, self._name, var_name, self._name),
! 812: ' return (-1);',
! 813: 'if (evtag_unmarshal_fixed(%s, %s, %s->%s_data, '
! 814: '%s->%s_length) == -1) {' % (
! 815: buf, tag_name, var_name, self._name, var_name, self._name),
! 816: ' event_warnx("%%s: failed to unmarshal %s", __func__);' % (
! 817: self._name ),
! 818: ' return (-1);',
! 819: '}'
! 820: ]
! 821: return code
! 822:
! 823: def CodeMarshal(self, buf, tag_name, var_name):
! 824: code = ['evtag_marshal(%s, %s, %s->%s_data, %s->%s_length);' % (
! 825: buf, tag_name, var_name, self._name, var_name, self._name)]
! 826: return code
! 827:
! 828: def CodeClear(self, structname):
! 829: code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
! 830: ' free (%s->%s_data);' % (structname, self.Name()),
! 831: ' %s->%s_data = NULL;' % (structname, self.Name()),
! 832: ' %s->%s_length = 0;' % (structname, self.Name()),
! 833: ' %s->%s_set = 0;' % (structname, self.Name()),
! 834: '}'
! 835: ]
! 836:
! 837: return code
! 838:
! 839: def CodeNew(self, name):
! 840: code = ['%s->%s_data = NULL;' % (name, self._name),
! 841: '%s->%s_length = 0;' % (name, self._name) ]
! 842: return code
! 843:
! 844: def CodeFree(self, name):
! 845: code = ['if (%s->%s_data != NULL)' % (name, self._name),
! 846: ' free (%s->%s_data); ' % (name, self._name)]
! 847:
! 848: return code
! 849:
! 850: def Declaration(self):
! 851: dcl = ['ev_uint8_t *%s_data;' % self._name,
! 852: 'ev_uint32_t %s_length;' % self._name]
! 853:
! 854: return dcl
! 855:
! 856: class EntryArray(Entry):
! 857: def __init__(self, entry):
! 858: # Init base class
! 859: Entry.__init__(self, entry._type, entry._name, entry._tag)
! 860:
! 861: self._entry = entry
! 862: self._refname = entry._refname
! 863: self._ctype = 'struct %s *' % self._refname
! 864:
! 865: def GetDeclaration(self, funcname):
! 866: """Allows direct access to elements of the array."""
! 867: translate = self.GetTranslation()
! 868: translate["funcname"] = funcname
! 869: code = [
! 870: 'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' %
! 871: translate ]
! 872: return code
! 873:
! 874: def AssignDeclaration(self, funcname):
! 875: code = [ 'int %s(struct %s *, int, const %s);' % (
! 876: funcname, self._struct.Name(), self._ctype ) ]
! 877: return code
! 878:
! 879: def AddDeclaration(self, funcname):
! 880: code = [ '%s %s(struct %s *);' % (
! 881: self._ctype, funcname, self._struct.Name() ) ]
! 882: return code
! 883:
! 884: def CodeGet(self):
! 885: code = """int
! 886: %(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset,
! 887: %(ctype)s *value)
! 888: {
! 889: if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length)
! 890: return (-1);
! 891: *value = msg->%(name)s_data[offset];
! 892: return (0);
! 893: }""" % self.GetTranslation()
! 894:
! 895: return code.split('\n')
! 896:
! 897: def CodeAssign(self):
! 898: code = """int
! 899: %(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off,
! 900: const %(ctype)s value)
! 901: {
! 902: struct evbuffer *tmp = NULL;
! 903: if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length)
! 904: return (-1);
! 905: %(refname)s_clear(msg->%(name)s_data[off]);
! 906: if ((tmp = evbuffer_new()) == NULL) {
! 907: event_warn("%%s: evbuffer_new()", __func__);
! 908: goto error;
! 909: }
! 910: %(refname)s_marshal(tmp, value);
! 911: if (%(refname)s_unmarshal(msg->%(name)s_data[off], tmp) == -1) {
! 912: event_warnx("%%s: %(refname)s_unmarshal", __func__);
! 913: goto error;
! 914: }
! 915: evbuffer_free(tmp);
! 916: return (0);
! 917: error:
! 918: if (tmp != NULL)
! 919: evbuffer_free(tmp);
! 920: %(refname)s_clear(msg->%(name)s_data[off]);
! 921: return (-1);
! 922: }""" % self.GetTranslation()
! 923:
! 924: return code.split('\n')
! 925:
! 926: def CodeAdd(self):
! 927: code = \
! 928: """%(ctype)s
! 929: %(parent_name)s_%(name)s_add(struct %(parent_name)s *msg)
! 930: {
! 931: if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) {
! 932: int tobe_allocated = msg->%(name)s_num_allocated;
! 933: %(ctype)s* new_data = NULL;
! 934: tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1;
! 935: new_data = (%(ctype)s*) realloc(msg->%(name)s_data,
! 936: tobe_allocated * sizeof(%(ctype)s));
! 937: if (new_data == NULL)
! 938: goto error;
! 939: msg->%(name)s_data = new_data;
! 940: msg->%(name)s_num_allocated = tobe_allocated;
! 941: }
! 942: msg->%(name)s_data[msg->%(name)s_length - 1] = %(refname)s_new();
! 943: if (msg->%(name)s_data[msg->%(name)s_length - 1] == NULL)
! 944: goto error;
! 945: msg->%(name)s_set = 1;
! 946: return (msg->%(name)s_data[msg->%(name)s_length - 1]);
! 947: error:
! 948: --msg->%(name)s_length;
! 949: return (NULL);
! 950: }
! 951: """ % self.GetTranslation()
! 952:
! 953: return code.split('\n')
! 954:
! 955: def CodeComplete(self, structname):
! 956: code = []
! 957: translate = self.GetTranslation()
! 958:
! 959: if self.Optional():
! 960: code.append( 'if (%(structname)s->%(name)s_set)' % translate)
! 961:
! 962: translate["structname"] = structname
! 963: tmp = """{
! 964: int i;
! 965: for (i = 0; i < %(structname)s->%(name)s_length; ++i) {
! 966: if (%(refname)s_complete(%(structname)s->%(name)s_data[i]) == -1)
! 967: return (-1);
! 968: }
! 969: }""" % translate
! 970: code.extend(tmp.split('\n'))
! 971:
! 972: return code
! 973:
! 974: def CodeUnmarshal(self, buf, tag_name, var_name):
! 975: translate = self.GetTranslation()
! 976: translate["var_name"] = var_name
! 977: translate["buf"] = buf
! 978: translate["tag_name"] = tag_name
! 979: code = """if (%(parent_name)s_%(name)s_add(%(var_name)s) == NULL)
! 980: return (-1);
! 981: if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag_name)s,
! 982: %(var_name)s->%(name)s_data[%(var_name)s->%(name)s_length - 1]) == -1) {
! 983: --%(var_name)s->%(name)s_length;
! 984: event_warnx("%%s: failed to unmarshal %(name)s", __func__);
! 985: return (-1);
! 986: }""" % translate
! 987:
! 988: return code.split('\n')
! 989:
! 990: def CodeMarshal(self, buf, tag_name, var_name):
! 991: code = ['{',
! 992: ' int i;',
! 993: ' for (i = 0; i < %s->%s_length; ++i) {' % (
! 994: var_name, self._name),
! 995: ' evtag_marshal_%s(%s, %s, %s->%s_data[i]);' % (
! 996: self._refname, buf, tag_name, var_name, self._name),
! 997: ' }',
! 998: '}'
! 999: ]
! 1000: return code
! 1001:
! 1002: def CodeClear(self, structname):
! 1003: code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()),
! 1004: ' int i;',
! 1005: ' for (i = 0; i < %s->%s_length; ++i) {' % (
! 1006: structname, self.Name()),
! 1007: ' %s_free(%s->%s_data[i]);' % (
! 1008: self._refname, structname, self.Name()),
! 1009: ' }',
! 1010: ' free(%s->%s_data);' % (structname, self.Name()),
! 1011: ' %s->%s_data = NULL;' % (structname, self.Name()),
! 1012: ' %s->%s_set = 0;' % (structname, self.Name()),
! 1013: ' %s->%s_length = 0;' % (structname, self.Name()),
! 1014: ' %s->%s_num_allocated = 0;' % (structname, self.Name()),
! 1015: '}'
! 1016: ]
! 1017:
! 1018: return code
! 1019:
! 1020: def CodeNew(self, name):
! 1021: code = ['%s->%s_data = NULL;' % (name, self._name),
! 1022: '%s->%s_length = 0;' % (name, self._name),
! 1023: '%s->%s_num_allocated = 0;' % (name, self._name)]
! 1024: return code
! 1025:
! 1026: def CodeFree(self, name):
! 1027: code = ['if (%s->%s_data != NULL) {' % (name, self._name),
! 1028: ' int i;',
! 1029: ' for (i = 0; i < %s->%s_length; ++i) {' % (
! 1030: name, self._name),
! 1031: ' %s_free(%s->%s_data[i]); ' % (
! 1032: self._refname, name, self._name),
! 1033: ' %s->%s_data[i] = NULL;' % (name, self._name),
! 1034: ' }',
! 1035: ' free(%s->%s_data);' % (name, self._name),
! 1036: ' %s->%s_data = NULL;' % (name, self._name),
! 1037: ' %s->%s_length = 0;' % (name, self._name),
! 1038: ' %s->%s_num_allocated = 0;' % (name, self._name),
! 1039: '}'
! 1040: ]
! 1041:
! 1042: return code
! 1043:
! 1044: def Declaration(self):
! 1045: dcl = ['struct %s **%s_data;' % (self._refname, self._name),
! 1046: 'int %s_length;' % self._name,
! 1047: 'int %s_num_allocated;' % self._name ]
! 1048:
! 1049: return dcl
! 1050:
! 1051: def NormalizeLine(line):
! 1052: global white
! 1053: global cppcomment
! 1054:
! 1055: line = cppcomment.sub('', line)
! 1056: line = line.strip()
! 1057: line = white.sub(' ', line)
! 1058:
! 1059: return line
! 1060:
! 1061: def ProcessOneEntry(newstruct, entry):
! 1062: optional = 0
! 1063: array = 0
! 1064: entry_type = ''
! 1065: name = ''
! 1066: tag = ''
! 1067: tag_set = None
! 1068: separator = ''
! 1069: fixed_length = ''
! 1070:
! 1071: tokens = entry.split(' ')
! 1072: while tokens:
! 1073: token = tokens[0]
! 1074: tokens = tokens[1:]
! 1075:
! 1076: if not entry_type:
! 1077: if not optional and token == 'optional':
! 1078: optional = 1
! 1079: continue
! 1080:
! 1081: if not array and token == 'array':
! 1082: array = 1
! 1083: continue
! 1084:
! 1085: if not entry_type:
! 1086: entry_type = token
! 1087: continue
! 1088:
! 1089: if not name:
! 1090: res = re.match(r'^([^\[\]]+)(\[.*\])?$', token)
! 1091: if not res:
! 1092: print >>sys.stderr, 'Cannot parse name: \"%s\" around %d' % (
! 1093: entry, line_count)
! 1094: sys.exit(1)
! 1095: name = res.group(1)
! 1096: fixed_length = res.group(2)
! 1097: if fixed_length:
! 1098: fixed_length = fixed_length[1:-1]
! 1099: continue
! 1100:
! 1101: if not separator:
! 1102: separator = token
! 1103: if separator != '=':
! 1104: print >>sys.stderr, 'Expected "=" after name \"%s\" got %s' % (
! 1105: name, token)
! 1106: sys.exit(1)
! 1107: continue
! 1108:
! 1109: if not tag_set:
! 1110: tag_set = 1
! 1111: if not re.match(r'^(0x)?[0-9]+$', token):
! 1112: print >>sys.stderr, 'Expected tag number: \"%s\"' % entry
! 1113: sys.exit(1)
! 1114: tag = int(token, 0)
! 1115: continue
! 1116:
! 1117: print >>sys.stderr, 'Cannot parse \"%s\"' % entry
! 1118: sys.exit(1)
! 1119:
! 1120: if not tag_set:
! 1121: print >>sys.stderr, 'Need tag number: \"%s\"' % entry
! 1122: sys.exit(1)
! 1123:
! 1124: # Create the right entry
! 1125: if entry_type == 'bytes':
! 1126: if fixed_length:
! 1127: newentry = EntryBytes(entry_type, name, tag, fixed_length)
! 1128: else:
! 1129: newentry = EntryVarBytes(entry_type, name, tag)
! 1130: elif entry_type == 'int' and not fixed_length:
! 1131: newentry = EntryInt(entry_type, name, tag)
! 1132: elif entry_type == 'string' and not fixed_length:
! 1133: newentry = EntryString(entry_type, name, tag)
! 1134: else:
! 1135: res = re.match(r'^struct\[(%s)\]$' % _STRUCT_RE,
! 1136: entry_type, re.IGNORECASE)
! 1137: if res:
! 1138: # References another struct defined in our file
! 1139: newentry = EntryStruct(entry_type, name, tag, res.group(1))
! 1140: else:
! 1141: print >>sys.stderr, 'Bad type: "%s" in "%s"' % (entry_type, entry)
! 1142: sys.exit(1)
! 1143:
! 1144: structs = []
! 1145:
! 1146: if optional:
! 1147: newentry.MakeOptional()
! 1148: if array:
! 1149: newentry.MakeArray()
! 1150:
! 1151: newentry.SetStruct(newstruct)
! 1152: newentry.SetLineCount(line_count)
! 1153: newentry.Verify()
! 1154:
! 1155: if array:
! 1156: # We need to encapsulate this entry into a struct
! 1157: newname = newentry.Name()+ '_array'
! 1158:
! 1159: # Now borgify the new entry.
! 1160: newentry = EntryArray(newentry)
! 1161: newentry.SetStruct(newstruct)
! 1162: newentry.SetLineCount(line_count)
! 1163: newentry.MakeArray()
! 1164:
! 1165: newstruct.AddEntry(newentry)
! 1166:
! 1167: return structs
! 1168:
! 1169: def ProcessStruct(data):
! 1170: tokens = data.split(' ')
! 1171:
! 1172: # First three tokens are: 'struct' 'name' '{'
! 1173: newstruct = Struct(tokens[1])
! 1174:
! 1175: inside = ' '.join(tokens[3:-1])
! 1176:
! 1177: tokens = inside.split(';')
! 1178:
! 1179: structs = []
! 1180:
! 1181: for entry in tokens:
! 1182: entry = NormalizeLine(entry)
! 1183: if not entry:
! 1184: continue
! 1185:
! 1186: # It's possible that new structs get defined in here
! 1187: structs.extend(ProcessOneEntry(newstruct, entry))
! 1188:
! 1189: structs.append(newstruct)
! 1190: return structs
! 1191:
! 1192: def GetNextStruct(file):
! 1193: global line_count
! 1194: global cppdirect
! 1195:
! 1196: got_struct = 0
! 1197:
! 1198: processed_lines = []
! 1199:
! 1200: have_c_comment = 0
! 1201: data = ''
! 1202: while 1:
! 1203: line = file.readline()
! 1204: if not line:
! 1205: break
! 1206:
! 1207: line_count += 1
! 1208: line = line[:-1]
! 1209:
! 1210: if not have_c_comment and re.search(r'/\*', line):
! 1211: if re.search(r'/\*.*\*/', line):
! 1212: line = re.sub(r'/\*.*\*/', '', line)
! 1213: else:
! 1214: line = re.sub(r'/\*.*$', '', line)
! 1215: have_c_comment = 1
! 1216:
! 1217: if have_c_comment:
! 1218: if not re.search(r'\*/', line):
! 1219: continue
! 1220: have_c_comment = 0
! 1221: line = re.sub(r'^.*\*/', '', line)
! 1222:
! 1223: line = NormalizeLine(line)
! 1224:
! 1225: if not line:
! 1226: continue
! 1227:
! 1228: if not got_struct:
! 1229: if re.match(r'#include ["<].*[>"]', line):
! 1230: cppdirect.append(line)
! 1231: continue
! 1232:
! 1233: if re.match(r'^#(if( |def)|endif)', line):
! 1234: cppdirect.append(line)
! 1235: continue
! 1236:
! 1237: if re.match(r'^#define', line):
! 1238: headerdirect.append(line)
! 1239: continue
! 1240:
! 1241: if not re.match(r'^struct %s {$' % _STRUCT_RE,
! 1242: line, re.IGNORECASE):
! 1243: print >>sys.stderr, 'Missing struct on line %d: %s' % (
! 1244: line_count, line)
! 1245: sys.exit(1)
! 1246: else:
! 1247: got_struct = 1
! 1248: data += line
! 1249: continue
! 1250:
! 1251: # We are inside the struct
! 1252: tokens = line.split('}')
! 1253: if len(tokens) == 1:
! 1254: data += ' ' + line
! 1255: continue
! 1256:
! 1257: if len(tokens[1]):
! 1258: print >>sys.stderr, 'Trailing garbage after struct on line %d' % (
! 1259: line_count )
! 1260: sys.exit(1)
! 1261:
! 1262: # We found the end of the struct
! 1263: data += ' %s}' % tokens[0]
! 1264: break
! 1265:
! 1266: # Remove any comments, that might be in there
! 1267: data = re.sub(r'/\*.*\*/', '', data)
! 1268:
! 1269: return data
! 1270:
! 1271:
! 1272: def Parse(file):
! 1273: """
! 1274: Parses the input file and returns C code and corresponding header file.
! 1275: """
! 1276:
! 1277: entities = []
! 1278:
! 1279: while 1:
! 1280: # Just gets the whole struct nicely formatted
! 1281: data = GetNextStruct(file)
! 1282:
! 1283: if not data:
! 1284: break
! 1285:
! 1286: entities.extend(ProcessStruct(data))
! 1287:
! 1288: return entities
! 1289:
! 1290: def GuardName(name):
! 1291: name = '_'.join(name.split('.'))
! 1292: name = '_'.join(name.split('/'))
! 1293: guard = '_'+name.upper()+'_'
! 1294:
! 1295: return guard
! 1296:
! 1297: def HeaderPreamble(name):
! 1298: guard = GuardName(name)
! 1299: pre = (
! 1300: '/*\n'
! 1301: ' * Automatically generated from %s\n'
! 1302: ' */\n\n'
! 1303: '#ifndef %s\n'
! 1304: '#define %s\n\n' ) % (
! 1305: name, guard, guard)
! 1306:
! 1307: # insert stdint.h - let's hope everyone has it
! 1308: pre += (
! 1309: '#include <event-config.h>\n'
! 1310: '#ifdef _EVENT_HAVE_STDINT_H\n'
! 1311: '#include <stdint.h>\n'
! 1312: '#endif\n' )
! 1313:
! 1314: for statement in headerdirect:
! 1315: pre += '%s\n' % statement
! 1316: if headerdirect:
! 1317: pre += '\n'
! 1318:
! 1319: pre += (
! 1320: '#define EVTAG_HAS(msg, member) ((msg)->member##_set == 1)\n'
! 1321: '#ifdef __GNUC__\n'
! 1322: '#define EVTAG_ASSIGN(msg, member, args...) '
! 1323: '(*(msg)->base->member##_assign)(msg, ## args)\n'
! 1324: '#define EVTAG_GET(msg, member, args...) '
! 1325: '(*(msg)->base->member##_get)(msg, ## args)\n'
! 1326: '#else\n'
! 1327: '#define EVTAG_ASSIGN(msg, member, ...) '
! 1328: '(*(msg)->base->member##_assign)(msg, ## __VA_ARGS__)\n'
! 1329: '#define EVTAG_GET(msg, member, ...) '
! 1330: '(*(msg)->base->member##_get)(msg, ## __VA_ARGS__)\n'
! 1331: '#endif\n'
! 1332: '#define EVTAG_ADD(msg, member) (*(msg)->base->member##_add)(msg)\n'
! 1333: '#define EVTAG_LEN(msg, member) ((msg)->member##_length)\n'
! 1334: )
! 1335:
! 1336: return pre
! 1337:
! 1338:
! 1339: def HeaderPostamble(name):
! 1340: guard = GuardName(name)
! 1341: return '#endif /* %s */' % guard
! 1342:
! 1343: def BodyPreamble(name):
! 1344: global _NAME
! 1345: global _VERSION
! 1346:
! 1347: header_file = '.'.join(name.split('.')[:-1]) + '.gen.h'
! 1348:
! 1349: pre = ( '/*\n'
! 1350: ' * Automatically generated from %s\n'
! 1351: ' * by %s/%s. DO NOT EDIT THIS FILE.\n'
! 1352: ' */\n\n' ) % (name, _NAME, _VERSION)
! 1353: pre += ( '#include <sys/types.h>\n'
! 1354: '#ifdef _EVENT_HAVE_SYS_TIME_H\n'
! 1355: '#include <sys/time.h>\n'
! 1356: '#endif\n'
! 1357: '#include <stdlib.h>\n'
! 1358: '#include <string.h>\n'
! 1359: '#include <assert.h>\n'
! 1360: '#define EVENT_NO_STRUCT\n'
! 1361: '#include <event.h>\n\n'
! 1362: '#ifdef _EVENT___func__\n'
! 1363: '#define __func__ _EVENT___func__\n'
! 1364: '#endif\n' )
! 1365:
! 1366: for statement in cppdirect:
! 1367: pre += '%s\n' % statement
! 1368:
! 1369: pre += '\n#include "%s"\n\n' % header_file
! 1370:
! 1371: pre += 'void event_err(int eval, const char *fmt, ...);\n'
! 1372: pre += 'void event_warn(const char *fmt, ...);\n'
! 1373: pre += 'void event_errx(int eval, const char *fmt, ...);\n'
! 1374: pre += 'void event_warnx(const char *fmt, ...);\n\n'
! 1375:
! 1376: return pre
! 1377:
! 1378: def main(argv):
! 1379: if len(argv) < 2 or not argv[1]:
! 1380: print >>sys.stderr, 'Need RPC description file as first argument.'
! 1381: sys.exit(1)
! 1382:
! 1383: filename = argv[1]
! 1384:
! 1385: ext = filename.split('.')[-1]
! 1386: if ext != 'rpc':
! 1387: print >>sys.stderr, 'Unrecognized file extension: %s' % ext
! 1388: sys.exit(1)
! 1389:
! 1390: print >>sys.stderr, 'Reading \"%s\"' % filename
! 1391:
! 1392: fp = open(filename, 'r')
! 1393: entities = Parse(fp)
! 1394: fp.close()
! 1395:
! 1396: header_file = '.'.join(filename.split('.')[:-1]) + '.gen.h'
! 1397: impl_file = '.'.join(filename.split('.')[:-1]) + '.gen.c'
! 1398:
! 1399: print >>sys.stderr, '... creating "%s"' % header_file
! 1400: header_fp = open(header_file, 'w')
! 1401: print >>header_fp, HeaderPreamble(filename)
! 1402:
! 1403: # Create forward declarations: allows other structs to reference
! 1404: # each other
! 1405: for entry in entities:
! 1406: entry.PrintForwardDeclaration(header_fp)
! 1407: print >>header_fp, ''
! 1408:
! 1409: for entry in entities:
! 1410: entry.PrintTags(header_fp)
! 1411: entry.PrintDeclaration(header_fp)
! 1412: print >>header_fp, HeaderPostamble(filename)
! 1413: header_fp.close()
! 1414:
! 1415: print >>sys.stderr, '... creating "%s"' % impl_file
! 1416: impl_fp = open(impl_file, 'w')
! 1417: print >>impl_fp, BodyPreamble(filename)
! 1418: for entry in entities:
! 1419: entry.PrintCode(impl_fp)
! 1420: impl_fp.close()
! 1421:
! 1422: if __name__ == '__main__':
! 1423: main(sys.argv)
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>