File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libevent / event_rpcgen.py
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:02:54 2012 UTC (12 years, 3 months ago) by misho
Branches: libevent, MAIN
CVS tags: v1_4_14bp0, v1_4_14b, HEAD
libevent

    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>