Annotation of embedaddon/libevent/event_rpcgen.py, revision 1.1.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>