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>