Index: third_party/libevent/event_rpcgen.py |
diff --git a/third_party/libevent/event_rpcgen.py b/third_party/libevent/event_rpcgen.py |
deleted file mode 100755 |
index 4ec77a6f6e315c7f03954a114bc6ab76a2cab6ad..0000000000000000000000000000000000000000 |
--- a/third_party/libevent/event_rpcgen.py |
+++ /dev/null |
@@ -1,1423 +0,0 @@ |
-#!/usr/bin/env python |
-# |
-# Copyright (c) 2005 Niels Provos <provos@citi.umich.edu> |
-# All rights reserved. |
-# |
-# Generates marshaling code based on libevent. |
- |
-import sys |
-import re |
- |
-# |
-_NAME = "event_rpcgen.py" |
-_VERSION = "0.1" |
-_STRUCT_RE = '[a-z][a-z_0-9]*' |
- |
-# Globals |
-line_count = 0 |
- |
-white = re.compile(r'^\s+') |
-cppcomment = re.compile(r'\/\/.*$') |
-headerdirect = [] |
-cppdirect = [] |
- |
-# Holds everything that makes a struct |
-class Struct: |
- def __init__(self, name): |
- self._name = name |
- self._entries = [] |
- self._tags = {} |
- print >>sys.stderr, ' Created struct: %s' % name |
- |
- def AddEntry(self, entry): |
- if self._tags.has_key(entry.Tag()): |
- print >>sys.stderr, ( 'Entry "%s" duplicates tag number ' |
- '%d from "%s" around line %d' ) % ( |
- entry.Name(), entry.Tag(), |
- self._tags[entry.Tag()], line_count) |
- sys.exit(1) |
- self._entries.append(entry) |
- self._tags[entry.Tag()] = entry.Name() |
- print >>sys.stderr, ' Added entry: %s' % entry.Name() |
- |
- def Name(self): |
- return self._name |
- |
- def EntryTagName(self, entry): |
- """Creates the name inside an enumeration for distinguishing data |
- types.""" |
- name = "%s_%s" % (self._name, entry.Name()) |
- return name.upper() |
- |
- def PrintIdented(self, file, ident, code): |
- """Takes an array, add indentation to each entry and prints it.""" |
- for entry in code: |
- print >>file, '%s%s' % (ident, entry) |
- |
- def PrintTags(self, file): |
- """Prints the tag definitions for a structure.""" |
- print >>file, '/* Tag definition for %s */' % self._name |
- print >>file, 'enum %s_ {' % self._name.lower() |
- for entry in self._entries: |
- print >>file, ' %s=%d,' % (self.EntryTagName(entry), |
- entry.Tag()) |
- print >>file, ' %s_MAX_TAGS' % (self._name.upper()) |
- print >>file, '};\n' |
- |
- def PrintForwardDeclaration(self, file): |
- print >>file, 'struct %s;' % self._name |
- |
- def PrintDeclaration(self, file): |
- print >>file, '/* Structure declaration for %s */' % self._name |
- print >>file, 'struct %s_access_ {' % self._name |
- for entry in self._entries: |
- dcl = entry.AssignDeclaration('(*%s_assign)' % entry.Name()) |
- dcl.extend( |
- entry.GetDeclaration('(*%s_get)' % entry.Name())) |
- if entry.Array(): |
- dcl.extend( |
- entry.AddDeclaration('(*%s_add)' % entry.Name())) |
- self.PrintIdented(file, ' ', dcl) |
- print >>file, '};\n' |
- |
- print >>file, 'struct %s {' % self._name |
- print >>file, ' struct %s_access_ *base;\n' % self._name |
- for entry in self._entries: |
- dcl = entry.Declaration() |
- self.PrintIdented(file, ' ', dcl) |
- print >>file, '' |
- for entry in self._entries: |
- print >>file, ' ev_uint8_t %s_set;' % entry.Name() |
- print >>file, '};\n' |
- |
- print >>file, \ |
-"""struct %(name)s *%(name)s_new(void); |
-void %(name)s_free(struct %(name)s *); |
-void %(name)s_clear(struct %(name)s *); |
-void %(name)s_marshal(struct evbuffer *, const struct %(name)s *); |
-int %(name)s_unmarshal(struct %(name)s *, struct evbuffer *); |
-int %(name)s_complete(struct %(name)s *); |
-void evtag_marshal_%(name)s(struct evbuffer *, ev_uint32_t, |
- const struct %(name)s *); |
-int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t, |
- struct %(name)s *);""" % { 'name' : self._name } |
- |
- |
- # Write a setting function of every variable |
- for entry in self._entries: |
- self.PrintIdented(file, '', entry.AssignDeclaration( |
- entry.AssignFuncName())) |
- self.PrintIdented(file, '', entry.GetDeclaration( |
- entry.GetFuncName())) |
- if entry.Array(): |
- self.PrintIdented(file, '', entry.AddDeclaration( |
- entry.AddFuncName())) |
- |
- print >>file, '/* --- %s done --- */\n' % self._name |
- |
- def PrintCode(self, file): |
- print >>file, ('/*\n' |
- ' * Implementation of %s\n' |
- ' */\n') % self._name |
- |
- print >>file, \ |
- 'static struct %(name)s_access_ __%(name)s_base = {' % \ |
- { 'name' : self._name } |
- for entry in self._entries: |
- self.PrintIdented(file, ' ', entry.CodeBase()) |
- print >>file, '};\n' |
- |
- # Creation |
- print >>file, ( |
- 'struct %(name)s *\n' |
- '%(name)s_new(void)\n' |
- '{\n' |
- ' struct %(name)s *tmp;\n' |
- ' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n' |
- ' event_warn("%%s: malloc", __func__);\n' |
- ' return (NULL);\n' |
- ' }\n' |
- ' tmp->base = &__%(name)s_base;\n') % { 'name' : self._name } |
- |
- for entry in self._entries: |
- self.PrintIdented(file, ' ', entry.CodeNew('tmp')) |
- print >>file, ' tmp->%s_set = 0;\n' % entry.Name() |
- |
- print >>file, ( |
- ' return (tmp);\n' |
- '}\n') |
- |
- # Adding |
- for entry in self._entries: |
- if entry.Array(): |
- self.PrintIdented(file, '', entry.CodeAdd()) |
- print >>file, '' |
- |
- # Assigning |
- for entry in self._entries: |
- self.PrintIdented(file, '', entry.CodeAssign()) |
- print >>file, '' |
- |
- # Getting |
- for entry in self._entries: |
- self.PrintIdented(file, '', entry.CodeGet()) |
- print >>file, '' |
- |
- # Clearing |
- print >>file, ( 'void\n' |
- '%(name)s_clear(struct %(name)s *tmp)\n' |
- '{' |
- ) % { 'name' : self._name } |
- for entry in self._entries: |
- self.PrintIdented(file, ' ', entry.CodeClear('tmp')) |
- |
- print >>file, '}\n' |
- |
- # Freeing |
- print >>file, ( 'void\n' |
- '%(name)s_free(struct %(name)s *tmp)\n' |
- '{' |
- ) % { 'name' : self._name } |
- |
- for entry in self._entries: |
- self.PrintIdented(file, ' ', entry.CodeFree('tmp')) |
- |
- print >>file, (' free(tmp);\n' |
- '}\n') |
- |
- # Marshaling |
- print >>file, ('void\n' |
- '%(name)s_marshal(struct evbuffer *evbuf, ' |
- 'const struct %(name)s *tmp)' |
- '{') % { 'name' : self._name } |
- for entry in self._entries: |
- indent = ' ' |
- # Optional entries do not have to be set |
- if entry.Optional(): |
- indent += ' ' |
- print >>file, ' if (tmp->%s_set) {' % entry.Name() |
- self.PrintIdented( |
- file, indent, |
- entry.CodeMarshal('evbuf', self.EntryTagName(entry), 'tmp')) |
- if entry.Optional(): |
- print >>file, ' }' |
- |
- print >>file, '}\n' |
- |
- # Unmarshaling |
- print >>file, ('int\n' |
- '%(name)s_unmarshal(struct %(name)s *tmp, ' |
- ' struct evbuffer *evbuf)\n' |
- '{\n' |
- ' ev_uint32_t tag;\n' |
- ' while (EVBUFFER_LENGTH(evbuf) > 0) {\n' |
- ' if (evtag_peek(evbuf, &tag) == -1)\n' |
- ' return (-1);\n' |
- ' switch (tag) {\n' |
- ) % { 'name' : self._name } |
- for entry in self._entries: |
- print >>file, ' case %s:\n' % self.EntryTagName(entry) |
- if not entry.Array(): |
- print >>file, ( |
- ' if (tmp->%s_set)\n' |
- ' return (-1);' |
- ) % (entry.Name()) |
- |
- self.PrintIdented( |
- file, ' ', |
- entry.CodeUnmarshal('evbuf', |
- self.EntryTagName(entry), 'tmp')) |
- |
- print >>file, ( ' tmp->%s_set = 1;\n' % entry.Name() + |
- ' break;\n' ) |
- print >>file, ( ' default:\n' |
- ' return -1;\n' |
- ' }\n' |
- ' }\n' ) |
- # Check if it was decoded completely |
- print >>file, ( ' if (%(name)s_complete(tmp) == -1)\n' |
- ' return (-1);' |
- ) % { 'name' : self._name } |
- |
- # Successfully decoded |
- print >>file, ( ' return (0);\n' |
- '}\n') |
- |
- # Checking if a structure has all the required data |
- print >>file, ( |
- 'int\n' |
- '%(name)s_complete(struct %(name)s *msg)\n' |
- '{' ) % { 'name' : self._name } |
- for entry in self._entries: |
- self.PrintIdented( |
- file, ' ', |
- entry.CodeComplete('msg')) |
- print >>file, ( |
- ' return (0);\n' |
- '}\n' ) |
- |
- # Complete message unmarshaling |
- print >>file, ( |
- 'int\n' |
- 'evtag_unmarshal_%(name)s(struct evbuffer *evbuf, ' |
- 'ev_uint32_t need_tag, struct %(name)s *msg)\n' |
- '{\n' |
- ' ev_uint32_t tag;\n' |
- ' int res = -1;\n' |
- '\n' |
- ' struct evbuffer *tmp = evbuffer_new();\n' |
- '\n' |
- ' if (evtag_unmarshal(evbuf, &tag, tmp) == -1' |
- ' || tag != need_tag)\n' |
- ' goto error;\n' |
- '\n' |
- ' if (%(name)s_unmarshal(msg, tmp) == -1)\n' |
- ' goto error;\n' |
- '\n' |
- ' res = 0;\n' |
- '\n' |
- ' error:\n' |
- ' evbuffer_free(tmp);\n' |
- ' return (res);\n' |
- '}\n' ) % { 'name' : self._name } |
- |
- # Complete message marshaling |
- print >>file, ( |
- 'void\n' |
- 'evtag_marshal_%(name)s(struct evbuffer *evbuf, ev_uint32_t tag, ' |
- 'const struct %(name)s *msg)\n' |
- '{\n' |
- ' struct evbuffer *_buf = evbuffer_new();\n' |
- ' assert(_buf != NULL);\n' |
- ' evbuffer_drain(_buf, -1);\n' |
- ' %(name)s_marshal(_buf, msg);\n' |
- ' evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf), ' |
- 'EVBUFFER_LENGTH(_buf));\n' |
- ' evbuffer_free(_buf);\n' |
- '}\n' ) % { 'name' : self._name } |
- |
-class Entry: |
- def __init__(self, type, name, tag): |
- self._type = type |
- self._name = name |
- self._tag = int(tag) |
- self._ctype = type |
- self._optional = 0 |
- self._can_be_array = 0 |
- self._array = 0 |
- self._line_count = -1 |
- self._struct = None |
- self._refname = None |
- |
- def GetTranslation(self): |
- return { "parent_name" : self._struct.Name(), |
- "name" : self._name, |
- "ctype" : self._ctype, |
- "refname" : self._refname |
- } |
- |
- def SetStruct(self, struct): |
- self._struct = struct |
- |
- def LineCount(self): |
- assert self._line_count != -1 |
- return self._line_count |
- |
- def SetLineCount(self, number): |
- self._line_count = number |
- |
- def Array(self): |
- return self._array |
- |
- def Optional(self): |
- return self._optional |
- |
- def Tag(self): |
- return self._tag |
- |
- def Name(self): |
- return self._name |
- |
- def Type(self): |
- return self._type |
- |
- def MakeArray(self, yes=1): |
- self._array = yes |
- |
- def MakeOptional(self): |
- self._optional = 1 |
- |
- def GetFuncName(self): |
- return '%s_%s_get' % (self._struct.Name(), self._name) |
- |
- def GetDeclaration(self, funcname): |
- code = [ 'int %s(struct %s *, %s *);' % ( |
- funcname, self._struct.Name(), self._ctype ) ] |
- return code |
- |
- def CodeGet(self): |
- code = ( |
- 'int', |
- '%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, ' |
- '%(ctype)s *value)', |
- '{', |
- ' if (msg->%(name)s_set != 1)', |
- ' return (-1);', |
- ' *value = msg->%(name)s_data;', |
- ' return (0);', |
- '}' ) |
- code = '\n'.join(code) |
- code = code % self.GetTranslation() |
- return code.split('\n') |
- |
- def AssignFuncName(self): |
- return '%s_%s_assign' % (self._struct.Name(), self._name) |
- |
- def AddFuncName(self): |
- return '%s_%s_add' % (self._struct.Name(), self._name) |
- |
- def AssignDeclaration(self, funcname): |
- code = [ 'int %s(struct %s *, const %s);' % ( |
- funcname, self._struct.Name(), self._ctype ) ] |
- return code |
- |
- def CodeAssign(self): |
- code = [ 'int', |
- '%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg,' |
- ' const %(ctype)s value)', |
- '{', |
- ' msg->%(name)s_set = 1;', |
- ' msg->%(name)s_data = value;', |
- ' return (0);', |
- '}' ] |
- code = '\n'.join(code) |
- code = code % self.GetTranslation() |
- return code.split('\n') |
- |
- def CodeClear(self, structname): |
- code = [ '%s->%s_set = 0;' % (structname, self.Name()) ] |
- |
- return code |
- |
- def CodeComplete(self, structname): |
- if self.Optional(): |
- return [] |
- |
- code = [ 'if (!%s->%s_set)' % (structname, self.Name()), |
- ' return (-1);' ] |
- |
- return code |
- |
- def CodeFree(self, name): |
- return [] |
- |
- def CodeBase(self): |
- code = [ |
- '%(parent_name)s_%(name)s_assign,', |
- '%(parent_name)s_%(name)s_get,' |
- ] |
- if self.Array(): |
- code.append('%(parent_name)s_%(name)s_add,') |
- |
- code = '\n'.join(code) |
- code = code % self.GetTranslation() |
- return code.split('\n') |
- |
- def Verify(self): |
- if self.Array() and not self._can_be_array: |
- print >>sys.stderr, ( |
- 'Entry "%s" cannot be created as an array ' |
- 'around line %d' ) % (self._name, self.LineCount()) |
- sys.exit(1) |
- if not self._struct: |
- print >>sys.stderr, ( |
- 'Entry "%s" does not know which struct it belongs to ' |
- 'around line %d' ) % (self._name, self.LineCount()) |
- sys.exit(1) |
- if self._optional and self._array: |
- print >>sys.stderr, ( 'Entry "%s" has illegal combination of ' |
- 'optional and array around line %d' ) % ( |
- self._name, self.LineCount() ) |
- sys.exit(1) |
- |
-class EntryBytes(Entry): |
- def __init__(self, type, name, tag, length): |
- # Init base class |
- Entry.__init__(self, type, name, tag) |
- |
- self._length = length |
- self._ctype = 'ev_uint8_t' |
- |
- def GetDeclaration(self, funcname): |
- code = [ 'int %s(struct %s *, %s **);' % ( |
- funcname, self._struct.Name(), self._ctype ) ] |
- return code |
- |
- def AssignDeclaration(self, funcname): |
- code = [ 'int %s(struct %s *, const %s *);' % ( |
- funcname, self._struct.Name(), self._ctype ) ] |
- return code |
- |
- def Declaration(self): |
- dcl = ['ev_uint8_t %s_data[%s];' % (self._name, self._length)] |
- |
- return dcl |
- |
- def CodeGet(self): |
- name = self._name |
- code = [ 'int', |
- '%s_%s_get(struct %s *msg, %s **value)' % ( |
- self._struct.Name(), name, |
- self._struct.Name(), self._ctype), |
- '{', |
- ' if (msg->%s_set != 1)' % name, |
- ' return (-1);', |
- ' *value = msg->%s_data;' % name, |
- ' return (0);', |
- '}' ] |
- return code |
- |
- def CodeAssign(self): |
- name = self._name |
- code = [ 'int', |
- '%s_%s_assign(struct %s *msg, const %s *value)' % ( |
- self._struct.Name(), name, |
- self._struct.Name(), self._ctype), |
- '{', |
- ' msg->%s_set = 1;' % name, |
- ' memcpy(msg->%s_data, value, %s);' % ( |
- name, self._length), |
- ' return (0);', |
- '}' ] |
- return code |
- |
- def CodeUnmarshal(self, buf, tag_name, var_name): |
- code = [ 'if (evtag_unmarshal_fixed(%s, %s, ' % (buf, tag_name) + |
- '%s->%s_data, ' % (var_name, self._name) + |
- 'sizeof(%s->%s_data)) == -1) {' % ( |
- var_name, self._name), |
- ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( |
- self._name ), |
- ' return (-1);', |
- '}' |
- ] |
- return code |
- |
- def CodeMarshal(self, buf, tag_name, var_name): |
- code = ['evtag_marshal(%s, %s, %s->%s_data, sizeof(%s->%s_data));' % ( |
- buf, tag_name, var_name, self._name, var_name, self._name )] |
- return code |
- |
- def CodeClear(self, structname): |
- code = [ '%s->%s_set = 0;' % (structname, self.Name()), |
- 'memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( |
- structname, self._name, structname, self._name)] |
- |
- return code |
- |
- def CodeNew(self, name): |
- code = ['memset(%s->%s_data, 0, sizeof(%s->%s_data));' % ( |
- name, self._name, name, self._name)] |
- return code |
- |
- def Verify(self): |
- if not self._length: |
- print >>sys.stderr, 'Entry "%s" needs a length around line %d' % ( |
- self._name, self.LineCount() ) |
- sys.exit(1) |
- |
- Entry.Verify(self) |
- |
-class EntryInt(Entry): |
- def __init__(self, type, name, tag): |
- # Init base class |
- Entry.__init__(self, type, name, tag) |
- |
- self._ctype = 'ev_uint32_t' |
- |
- def CodeUnmarshal(self, buf, tag_name, var_name): |
- code = ['if (evtag_unmarshal_int(%s, %s, &%s->%s_data) == -1) {' % ( |
- buf, tag_name, var_name, self._name), |
- ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( |
- self._name ), |
- ' return (-1);', |
- '}' ] |
- return code |
- |
- def CodeMarshal(self, buf, tag_name, var_name): |
- code = ['evtag_marshal_int(%s, %s, %s->%s_data);' % ( |
- buf, tag_name, var_name, self._name)] |
- return code |
- |
- def Declaration(self): |
- dcl = ['ev_uint32_t %s_data;' % self._name] |
- |
- return dcl |
- |
- def CodeNew(self, name): |
- code = ['%s->%s_data = 0;' % (name, self._name)] |
- return code |
- |
-class EntryString(Entry): |
- def __init__(self, type, name, tag): |
- # Init base class |
- Entry.__init__(self, type, name, tag) |
- |
- self._ctype = 'char *' |
- |
- def CodeAssign(self): |
- name = self._name |
- code = """int |
-%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, |
- const %(ctype)s value) |
-{ |
- if (msg->%(name)s_data != NULL) |
- free(msg->%(name)s_data); |
- if ((msg->%(name)s_data = strdup(value)) == NULL) |
- return (-1); |
- msg->%(name)s_set = 1; |
- return (0); |
-}""" % self.GetTranslation() |
- |
- return code.split('\n') |
- |
- def CodeUnmarshal(self, buf, tag_name, var_name): |
- code = ['if (evtag_unmarshal_string(%s, %s, &%s->%s_data) == -1) {' % ( |
- buf, tag_name, var_name, self._name), |
- ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( |
- self._name ), |
- ' return (-1);', |
- '}' |
- ] |
- return code |
- |
- def CodeMarshal(self, buf, tag_name, var_name): |
- code = ['evtag_marshal_string(%s, %s, %s->%s_data);' % ( |
- buf, tag_name, var_name, self._name)] |
- return code |
- |
- def CodeClear(self, structname): |
- code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), |
- ' free (%s->%s_data);' % (structname, self.Name()), |
- ' %s->%s_data = NULL;' % (structname, self.Name()), |
- ' %s->%s_set = 0;' % (structname, self.Name()), |
- '}' |
- ] |
- |
- return code |
- |
- def CodeNew(self, name): |
- code = ['%s->%s_data = NULL;' % (name, self._name)] |
- return code |
- |
- def CodeFree(self, name): |
- code = ['if (%s->%s_data != NULL)' % (name, self._name), |
- ' free (%s->%s_data); ' % (name, self._name)] |
- |
- return code |
- |
- def Declaration(self): |
- dcl = ['char *%s_data;' % self._name] |
- |
- return dcl |
- |
-class EntryStruct(Entry): |
- def __init__(self, type, name, tag, refname): |
- # Init base class |
- Entry.__init__(self, type, name, tag) |
- |
- self._can_be_array = 1 |
- self._refname = refname |
- self._ctype = 'struct %s*' % refname |
- |
- def CodeGet(self): |
- name = self._name |
- code = [ 'int', |
- '%s_%s_get(struct %s *msg, %s *value)' % ( |
- self._struct.Name(), name, |
- self._struct.Name(), self._ctype), |
- '{', |
- ' if (msg->%s_set != 1) {' % name, |
- ' msg->%s_data = %s_new();' % (name, self._refname), |
- ' if (msg->%s_data == NULL)' % name, |
- ' return (-1);', |
- ' msg->%s_set = 1;' % name, |
- ' }', |
- ' *value = msg->%s_data;' % name, |
- ' return (0);', |
- '}' ] |
- return code |
- |
- def CodeAssign(self): |
- name = self._name |
- code = """int |
-%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, |
- const %(ctype)s value) |
-{ |
- struct evbuffer *tmp = NULL; |
- if (msg->%(name)s_set) { |
- %(refname)s_clear(msg->%(name)s_data); |
- msg->%(name)s_set = 0; |
- } else { |
- msg->%(name)s_data = %(refname)s_new(); |
- if (msg->%(name)s_data == NULL) { |
- event_warn("%%s: %(refname)s_new()", __func__); |
- goto error; |
- } |
- } |
- if ((tmp = evbuffer_new()) == NULL) { |
- event_warn("%%s: evbuffer_new()", __func__); |
- goto error; |
- } |
- %(refname)s_marshal(tmp, value); |
- if (%(refname)s_unmarshal(msg->%(name)s_data, tmp) == -1) { |
- event_warnx("%%s: %(refname)s_unmarshal", __func__); |
- goto error; |
- } |
- msg->%(name)s_set = 1; |
- evbuffer_free(tmp); |
- return (0); |
- error: |
- if (tmp != NULL) |
- evbuffer_free(tmp); |
- if (msg->%(name)s_data != NULL) { |
- %(refname)s_free(msg->%(name)s_data); |
- msg->%(name)s_data = NULL; |
- } |
- return (-1); |
-}""" % self.GetTranslation() |
- return code.split('\n') |
- |
- def CodeComplete(self, structname): |
- if self.Optional(): |
- code = [ 'if (%s->%s_set && %s_complete(%s->%s_data) == -1)' % ( |
- structname, self.Name(), |
- self._refname, structname, self.Name()), |
- ' return (-1);' ] |
- else: |
- code = [ 'if (%s_complete(%s->%s_data) == -1)' % ( |
- self._refname, structname, self.Name()), |
- ' return (-1);' ] |
- |
- return code |
- |
- def CodeUnmarshal(self, buf, tag_name, var_name): |
- code = ['%s->%s_data = %s_new();' % ( |
- var_name, self._name, self._refname), |
- 'if (%s->%s_data == NULL)' % (var_name, self._name), |
- ' return (-1);', |
- 'if (evtag_unmarshal_%s(%s, %s, %s->%s_data) == -1) {' % ( |
- self._refname, buf, tag_name, var_name, self._name), |
- ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( |
- self._name ), |
- ' return (-1);', |
- '}' |
- ] |
- return code |
- |
- def CodeMarshal(self, buf, tag_name, var_name): |
- code = ['evtag_marshal_%s(%s, %s, %s->%s_data);' % ( |
- self._refname, buf, tag_name, var_name, self._name)] |
- return code |
- |
- def CodeClear(self, structname): |
- code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), |
- ' %s_free(%s->%s_data);' % ( |
- self._refname, structname, self.Name()), |
- ' %s->%s_data = NULL;' % (structname, self.Name()), |
- ' %s->%s_set = 0;' % (structname, self.Name()), |
- '}' |
- ] |
- |
- return code |
- |
- def CodeNew(self, name): |
- code = ['%s->%s_data = NULL;' % (name, self._name)] |
- return code |
- |
- def CodeFree(self, name): |
- code = ['if (%s->%s_data != NULL)' % (name, self._name), |
- ' %s_free(%s->%s_data); ' % ( |
- self._refname, name, self._name)] |
- |
- return code |
- |
- def Declaration(self): |
- dcl = ['%s %s_data;' % (self._ctype, self._name)] |
- |
- return dcl |
- |
-class EntryVarBytes(Entry): |
- def __init__(self, type, name, tag): |
- # Init base class |
- Entry.__init__(self, type, name, tag) |
- |
- self._ctype = 'ev_uint8_t *' |
- |
- def GetDeclaration(self, funcname): |
- code = [ 'int %s(struct %s *, %s *, ev_uint32_t *);' % ( |
- funcname, self._struct.Name(), self._ctype ) ] |
- return code |
- |
- def AssignDeclaration(self, funcname): |
- code = [ 'int %s(struct %s *, const %s, ev_uint32_t);' % ( |
- funcname, self._struct.Name(), self._ctype ) ] |
- return code |
- |
- def CodeAssign(self): |
- name = self._name |
- code = [ 'int', |
- '%s_%s_assign(struct %s *msg, ' |
- 'const %s value, ev_uint32_t len)' % ( |
- self._struct.Name(), name, |
- self._struct.Name(), self._ctype), |
- '{', |
- ' if (msg->%s_data != NULL)' % name, |
- ' free (msg->%s_data);' % name, |
- ' msg->%s_data = malloc(len);' % name, |
- ' if (msg->%s_data == NULL)' % name, |
- ' return (-1);', |
- ' msg->%s_set = 1;' % name, |
- ' msg->%s_length = len;' % name, |
- ' memcpy(msg->%s_data, value, len);' % name, |
- ' return (0);', |
- '}' ] |
- return code |
- |
- def CodeGet(self): |
- name = self._name |
- code = [ 'int', |
- '%s_%s_get(struct %s *msg, %s *value, ev_uint32_t *plen)' % ( |
- self._struct.Name(), name, |
- self._struct.Name(), self._ctype), |
- '{', |
- ' if (msg->%s_set != 1)' % name, |
- ' return (-1);', |
- ' *value = msg->%s_data;' % name, |
- ' *plen = msg->%s_length;' % name, |
- ' return (0);', |
- '}' ] |
- return code |
- |
- def CodeUnmarshal(self, buf, tag_name, var_name): |
- code = ['if (evtag_payload_length(%s, &%s->%s_length) == -1)' % ( |
- buf, var_name, self._name), |
- ' return (-1);', |
- # We do not want DoS opportunities |
- 'if (%s->%s_length > EVBUFFER_LENGTH(%s))' % ( |
- var_name, self._name, buf), |
- ' return (-1);', |
- 'if ((%s->%s_data = malloc(%s->%s_length)) == NULL)' % ( |
- var_name, self._name, var_name, self._name), |
- ' return (-1);', |
- 'if (evtag_unmarshal_fixed(%s, %s, %s->%s_data, ' |
- '%s->%s_length) == -1) {' % ( |
- buf, tag_name, var_name, self._name, var_name, self._name), |
- ' event_warnx("%%s: failed to unmarshal %s", __func__);' % ( |
- self._name ), |
- ' return (-1);', |
- '}' |
- ] |
- return code |
- |
- def CodeMarshal(self, buf, tag_name, var_name): |
- code = ['evtag_marshal(%s, %s, %s->%s_data, %s->%s_length);' % ( |
- buf, tag_name, var_name, self._name, var_name, self._name)] |
- return code |
- |
- def CodeClear(self, structname): |
- code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), |
- ' free (%s->%s_data);' % (structname, self.Name()), |
- ' %s->%s_data = NULL;' % (structname, self.Name()), |
- ' %s->%s_length = 0;' % (structname, self.Name()), |
- ' %s->%s_set = 0;' % (structname, self.Name()), |
- '}' |
- ] |
- |
- return code |
- |
- def CodeNew(self, name): |
- code = ['%s->%s_data = NULL;' % (name, self._name), |
- '%s->%s_length = 0;' % (name, self._name) ] |
- return code |
- |
- def CodeFree(self, name): |
- code = ['if (%s->%s_data != NULL)' % (name, self._name), |
- ' free (%s->%s_data); ' % (name, self._name)] |
- |
- return code |
- |
- def Declaration(self): |
- dcl = ['ev_uint8_t *%s_data;' % self._name, |
- 'ev_uint32_t %s_length;' % self._name] |
- |
- return dcl |
- |
-class EntryArray(Entry): |
- def __init__(self, entry): |
- # Init base class |
- Entry.__init__(self, entry._type, entry._name, entry._tag) |
- |
- self._entry = entry |
- self._refname = entry._refname |
- self._ctype = 'struct %s *' % self._refname |
- |
- def GetDeclaration(self, funcname): |
- """Allows direct access to elements of the array.""" |
- translate = self.GetTranslation() |
- translate["funcname"] = funcname |
- code = [ |
- 'int %(funcname)s(struct %(parent_name)s *, int, %(ctype)s *);' % |
- translate ] |
- return code |
- |
- def AssignDeclaration(self, funcname): |
- code = [ 'int %s(struct %s *, int, const %s);' % ( |
- funcname, self._struct.Name(), self._ctype ) ] |
- return code |
- |
- def AddDeclaration(self, funcname): |
- code = [ '%s %s(struct %s *);' % ( |
- self._ctype, funcname, self._struct.Name() ) ] |
- return code |
- |
- def CodeGet(self): |
- code = """int |
-%(parent_name)s_%(name)s_get(struct %(parent_name)s *msg, int offset, |
- %(ctype)s *value) |
-{ |
- if (!msg->%(name)s_set || offset < 0 || offset >= msg->%(name)s_length) |
- return (-1); |
- *value = msg->%(name)s_data[offset]; |
- return (0); |
-}""" % self.GetTranslation() |
- |
- return code.split('\n') |
- |
- def CodeAssign(self): |
- code = """int |
-%(parent_name)s_%(name)s_assign(struct %(parent_name)s *msg, int off, |
- const %(ctype)s value) |
-{ |
- struct evbuffer *tmp = NULL; |
- if (!msg->%(name)s_set || off < 0 || off >= msg->%(name)s_length) |
- return (-1); |
- %(refname)s_clear(msg->%(name)s_data[off]); |
- if ((tmp = evbuffer_new()) == NULL) { |
- event_warn("%%s: evbuffer_new()", __func__); |
- goto error; |
- } |
- %(refname)s_marshal(tmp, value); |
- if (%(refname)s_unmarshal(msg->%(name)s_data[off], tmp) == -1) { |
- event_warnx("%%s: %(refname)s_unmarshal", __func__); |
- goto error; |
- } |
- evbuffer_free(tmp); |
- return (0); |
-error: |
- if (tmp != NULL) |
- evbuffer_free(tmp); |
- %(refname)s_clear(msg->%(name)s_data[off]); |
- return (-1); |
-}""" % self.GetTranslation() |
- |
- return code.split('\n') |
- |
- def CodeAdd(self): |
- code = \ |
-"""%(ctype)s |
-%(parent_name)s_%(name)s_add(struct %(parent_name)s *msg) |
-{ |
- if (++msg->%(name)s_length >= msg->%(name)s_num_allocated) { |
- int tobe_allocated = msg->%(name)s_num_allocated; |
- %(ctype)s* new_data = NULL; |
- tobe_allocated = !tobe_allocated ? 1 : tobe_allocated << 1; |
- new_data = (%(ctype)s*) realloc(msg->%(name)s_data, |
- tobe_allocated * sizeof(%(ctype)s)); |
- if (new_data == NULL) |
- goto error; |
- msg->%(name)s_data = new_data; |
- msg->%(name)s_num_allocated = tobe_allocated; |
- } |
- msg->%(name)s_data[msg->%(name)s_length - 1] = %(refname)s_new(); |
- if (msg->%(name)s_data[msg->%(name)s_length - 1] == NULL) |
- goto error; |
- msg->%(name)s_set = 1; |
- return (msg->%(name)s_data[msg->%(name)s_length - 1]); |
-error: |
- --msg->%(name)s_length; |
- return (NULL); |
-} |
- """ % self.GetTranslation() |
- |
- return code.split('\n') |
- |
- def CodeComplete(self, structname): |
- code = [] |
- translate = self.GetTranslation() |
- |
- if self.Optional(): |
- code.append( 'if (%(structname)s->%(name)s_set)' % translate) |
- |
- translate["structname"] = structname |
- tmp = """{ |
- int i; |
- for (i = 0; i < %(structname)s->%(name)s_length; ++i) { |
- if (%(refname)s_complete(%(structname)s->%(name)s_data[i]) == -1) |
- return (-1); |
- } |
-}""" % translate |
- code.extend(tmp.split('\n')) |
- |
- return code |
- |
- def CodeUnmarshal(self, buf, tag_name, var_name): |
- translate = self.GetTranslation() |
- translate["var_name"] = var_name |
- translate["buf"] = buf |
- translate["tag_name"] = tag_name |
- code = """if (%(parent_name)s_%(name)s_add(%(var_name)s) == NULL) |
- return (-1); |
-if (evtag_unmarshal_%(refname)s(%(buf)s, %(tag_name)s, |
- %(var_name)s->%(name)s_data[%(var_name)s->%(name)s_length - 1]) == -1) { |
- --%(var_name)s->%(name)s_length; |
- event_warnx("%%s: failed to unmarshal %(name)s", __func__); |
- return (-1); |
-}""" % translate |
- |
- return code.split('\n') |
- |
- def CodeMarshal(self, buf, tag_name, var_name): |
- code = ['{', |
- ' int i;', |
- ' for (i = 0; i < %s->%s_length; ++i) {' % ( |
- var_name, self._name), |
- ' evtag_marshal_%s(%s, %s, %s->%s_data[i]);' % ( |
- self._refname, buf, tag_name, var_name, self._name), |
- ' }', |
- '}' |
- ] |
- return code |
- |
- def CodeClear(self, structname): |
- code = [ 'if (%s->%s_set == 1) {' % (structname, self.Name()), |
- ' int i;', |
- ' for (i = 0; i < %s->%s_length; ++i) {' % ( |
- structname, self.Name()), |
- ' %s_free(%s->%s_data[i]);' % ( |
- self._refname, structname, self.Name()), |
- ' }', |
- ' free(%s->%s_data);' % (structname, self.Name()), |
- ' %s->%s_data = NULL;' % (structname, self.Name()), |
- ' %s->%s_set = 0;' % (structname, self.Name()), |
- ' %s->%s_length = 0;' % (structname, self.Name()), |
- ' %s->%s_num_allocated = 0;' % (structname, self.Name()), |
- '}' |
- ] |
- |
- return code |
- |
- def CodeNew(self, name): |
- code = ['%s->%s_data = NULL;' % (name, self._name), |
- '%s->%s_length = 0;' % (name, self._name), |
- '%s->%s_num_allocated = 0;' % (name, self._name)] |
- return code |
- |
- def CodeFree(self, name): |
- code = ['if (%s->%s_data != NULL) {' % (name, self._name), |
- ' int i;', |
- ' for (i = 0; i < %s->%s_length; ++i) {' % ( |
- name, self._name), |
- ' %s_free(%s->%s_data[i]); ' % ( |
- self._refname, name, self._name), |
- ' %s->%s_data[i] = NULL;' % (name, self._name), |
- ' }', |
- ' free(%s->%s_data);' % (name, self._name), |
- ' %s->%s_data = NULL;' % (name, self._name), |
- ' %s->%s_length = 0;' % (name, self._name), |
- ' %s->%s_num_allocated = 0;' % (name, self._name), |
- '}' |
- ] |
- |
- return code |
- |
- def Declaration(self): |
- dcl = ['struct %s **%s_data;' % (self._refname, self._name), |
- 'int %s_length;' % self._name, |
- 'int %s_num_allocated;' % self._name ] |
- |
- return dcl |
- |
-def NormalizeLine(line): |
- global white |
- global cppcomment |
- |
- line = cppcomment.sub('', line) |
- line = line.strip() |
- line = white.sub(' ', line) |
- |
- return line |
- |
-def ProcessOneEntry(newstruct, entry): |
- optional = 0 |
- array = 0 |
- entry_type = '' |
- name = '' |
- tag = '' |
- tag_set = None |
- separator = '' |
- fixed_length = '' |
- |
- tokens = entry.split(' ') |
- while tokens: |
- token = tokens[0] |
- tokens = tokens[1:] |
- |
- if not entry_type: |
- if not optional and token == 'optional': |
- optional = 1 |
- continue |
- |
- if not array and token == 'array': |
- array = 1 |
- continue |
- |
- if not entry_type: |
- entry_type = token |
- continue |
- |
- if not name: |
- res = re.match(r'^([^\[\]]+)(\[.*\])?$', token) |
- if not res: |
- print >>sys.stderr, 'Cannot parse name: \"%s\" around %d' % ( |
- entry, line_count) |
- sys.exit(1) |
- name = res.group(1) |
- fixed_length = res.group(2) |
- if fixed_length: |
- fixed_length = fixed_length[1:-1] |
- continue |
- |
- if not separator: |
- separator = token |
- if separator != '=': |
- print >>sys.stderr, 'Expected "=" after name \"%s\" got %s' % ( |
- name, token) |
- sys.exit(1) |
- continue |
- |
- if not tag_set: |
- tag_set = 1 |
- if not re.match(r'^(0x)?[0-9]+$', token): |
- print >>sys.stderr, 'Expected tag number: \"%s\"' % entry |
- sys.exit(1) |
- tag = int(token, 0) |
- continue |
- |
- print >>sys.stderr, 'Cannot parse \"%s\"' % entry |
- sys.exit(1) |
- |
- if not tag_set: |
- print >>sys.stderr, 'Need tag number: \"%s\"' % entry |
- sys.exit(1) |
- |
- # Create the right entry |
- if entry_type == 'bytes': |
- if fixed_length: |
- newentry = EntryBytes(entry_type, name, tag, fixed_length) |
- else: |
- newentry = EntryVarBytes(entry_type, name, tag) |
- elif entry_type == 'int' and not fixed_length: |
- newentry = EntryInt(entry_type, name, tag) |
- elif entry_type == 'string' and not fixed_length: |
- newentry = EntryString(entry_type, name, tag) |
- else: |
- res = re.match(r'^struct\[(%s)\]$' % _STRUCT_RE, |
- entry_type, re.IGNORECASE) |
- if res: |
- # References another struct defined in our file |
- newentry = EntryStruct(entry_type, name, tag, res.group(1)) |
- else: |
- print >>sys.stderr, 'Bad type: "%s" in "%s"' % (entry_type, entry) |
- sys.exit(1) |
- |
- structs = [] |
- |
- if optional: |
- newentry.MakeOptional() |
- if array: |
- newentry.MakeArray() |
- |
- newentry.SetStruct(newstruct) |
- newentry.SetLineCount(line_count) |
- newentry.Verify() |
- |
- if array: |
- # We need to encapsulate this entry into a struct |
- newname = newentry.Name()+ '_array' |
- |
- # Now borgify the new entry. |
- newentry = EntryArray(newentry) |
- newentry.SetStruct(newstruct) |
- newentry.SetLineCount(line_count) |
- newentry.MakeArray() |
- |
- newstruct.AddEntry(newentry) |
- |
- return structs |
- |
-def ProcessStruct(data): |
- tokens = data.split(' ') |
- |
- # First three tokens are: 'struct' 'name' '{' |
- newstruct = Struct(tokens[1]) |
- |
- inside = ' '.join(tokens[3:-1]) |
- |
- tokens = inside.split(';') |
- |
- structs = [] |
- |
- for entry in tokens: |
- entry = NormalizeLine(entry) |
- if not entry: |
- continue |
- |
- # It's possible that new structs get defined in here |
- structs.extend(ProcessOneEntry(newstruct, entry)) |
- |
- structs.append(newstruct) |
- return structs |
- |
-def GetNextStruct(file): |
- global line_count |
- global cppdirect |
- |
- got_struct = 0 |
- |
- processed_lines = [] |
- |
- have_c_comment = 0 |
- data = '' |
- while 1: |
- line = file.readline() |
- if not line: |
- break |
- |
- line_count += 1 |
- line = line[:-1] |
- |
- if not have_c_comment and re.search(r'/\*', line): |
- if re.search(r'/\*.*\*/', line): |
- line = re.sub(r'/\*.*\*/', '', line) |
- else: |
- line = re.sub(r'/\*.*$', '', line) |
- have_c_comment = 1 |
- |
- if have_c_comment: |
- if not re.search(r'\*/', line): |
- continue |
- have_c_comment = 0 |
- line = re.sub(r'^.*\*/', '', line) |
- |
- line = NormalizeLine(line) |
- |
- if not line: |
- continue |
- |
- if not got_struct: |
- if re.match(r'#include ["<].*[>"]', line): |
- cppdirect.append(line) |
- continue |
- |
- if re.match(r'^#(if( |def)|endif)', line): |
- cppdirect.append(line) |
- continue |
- |
- if re.match(r'^#define', line): |
- headerdirect.append(line) |
- continue |
- |
- if not re.match(r'^struct %s {$' % _STRUCT_RE, |
- line, re.IGNORECASE): |
- print >>sys.stderr, 'Missing struct on line %d: %s' % ( |
- line_count, line) |
- sys.exit(1) |
- else: |
- got_struct = 1 |
- data += line |
- continue |
- |
- # We are inside the struct |
- tokens = line.split('}') |
- if len(tokens) == 1: |
- data += ' ' + line |
- continue |
- |
- if len(tokens[1]): |
- print >>sys.stderr, 'Trailing garbage after struct on line %d' % ( |
- line_count ) |
- sys.exit(1) |
- |
- # We found the end of the struct |
- data += ' %s}' % tokens[0] |
- break |
- |
- # Remove any comments, that might be in there |
- data = re.sub(r'/\*.*\*/', '', data) |
- |
- return data |
- |
- |
-def Parse(file): |
- """ |
- Parses the input file and returns C code and corresponding header file. |
- """ |
- |
- entities = [] |
- |
- while 1: |
- # Just gets the whole struct nicely formatted |
- data = GetNextStruct(file) |
- |
- if not data: |
- break |
- |
- entities.extend(ProcessStruct(data)) |
- |
- return entities |
- |
-def GuardName(name): |
- name = '_'.join(name.split('.')) |
- name = '_'.join(name.split('/')) |
- guard = '_'+name.upper()+'_' |
- |
- return guard |
- |
-def HeaderPreamble(name): |
- guard = GuardName(name) |
- pre = ( |
- '/*\n' |
- ' * Automatically generated from %s\n' |
- ' */\n\n' |
- '#ifndef %s\n' |
- '#define %s\n\n' ) % ( |
- name, guard, guard) |
- |
- # insert stdint.h - let's hope everyone has it |
- pre += ( |
- '#include <event-config.h>\n' |
- '#ifdef _EVENT_HAVE_STDINT_H\n' |
- '#include <stdint.h>\n' |
- '#endif\n' ) |
- |
- for statement in headerdirect: |
- pre += '%s\n' % statement |
- if headerdirect: |
- pre += '\n' |
- |
- pre += ( |
- '#define EVTAG_HAS(msg, member) ((msg)->member##_set == 1)\n' |
- '#ifdef __GNUC__\n' |
- '#define EVTAG_ASSIGN(msg, member, args...) ' |
- '(*(msg)->base->member##_assign)(msg, ## args)\n' |
- '#define EVTAG_GET(msg, member, args...) ' |
- '(*(msg)->base->member##_get)(msg, ## args)\n' |
- '#else\n' |
- '#define EVTAG_ASSIGN(msg, member, ...) ' |
- '(*(msg)->base->member##_assign)(msg, ## __VA_ARGS__)\n' |
- '#define EVTAG_GET(msg, member, ...) ' |
- '(*(msg)->base->member##_get)(msg, ## __VA_ARGS__)\n' |
- '#endif\n' |
- '#define EVTAG_ADD(msg, member) (*(msg)->base->member##_add)(msg)\n' |
- '#define EVTAG_LEN(msg, member) ((msg)->member##_length)\n' |
- ) |
- |
- return pre |
- |
- |
-def HeaderPostamble(name): |
- guard = GuardName(name) |
- return '#endif /* %s */' % guard |
- |
-def BodyPreamble(name): |
- global _NAME |
- global _VERSION |
- |
- header_file = '.'.join(name.split('.')[:-1]) + '.gen.h' |
- |
- pre = ( '/*\n' |
- ' * Automatically generated from %s\n' |
- ' * by %s/%s. DO NOT EDIT THIS FILE.\n' |
- ' */\n\n' ) % (name, _NAME, _VERSION) |
- pre += ( '#include <sys/types.h>\n' |
- '#ifdef _EVENT_HAVE_SYS_TIME_H\n' |
- '#include <sys/time.h>\n' |
- '#endif\n' |
- '#include <stdlib.h>\n' |
- '#include <string.h>\n' |
- '#include <assert.h>\n' |
- '#define EVENT_NO_STRUCT\n' |
- '#include <event.h>\n\n' |
- '#ifdef _EVENT___func__\n' |
- '#define __func__ _EVENT___func__\n' |
- '#endif\n' ) |
- |
- for statement in cppdirect: |
- pre += '%s\n' % statement |
- |
- pre += '\n#include "%s"\n\n' % header_file |
- |
- pre += 'void event_err(int eval, const char *fmt, ...);\n' |
- pre += 'void event_warn(const char *fmt, ...);\n' |
- pre += 'void event_errx(int eval, const char *fmt, ...);\n' |
- pre += 'void event_warnx(const char *fmt, ...);\n\n' |
- |
- return pre |
- |
-def main(argv): |
- if len(argv) < 2 or not argv[1]: |
- print >>sys.stderr, 'Need RPC description file as first argument.' |
- sys.exit(1) |
- |
- filename = argv[1] |
- |
- ext = filename.split('.')[-1] |
- if ext != 'rpc': |
- print >>sys.stderr, 'Unrecognized file extension: %s' % ext |
- sys.exit(1) |
- |
- print >>sys.stderr, 'Reading \"%s\"' % filename |
- |
- fp = open(filename, 'r') |
- entities = Parse(fp) |
- fp.close() |
- |
- header_file = '.'.join(filename.split('.')[:-1]) + '.gen.h' |
- impl_file = '.'.join(filename.split('.')[:-1]) + '.gen.c' |
- |
- print >>sys.stderr, '... creating "%s"' % header_file |
- header_fp = open(header_file, 'w') |
- print >>header_fp, HeaderPreamble(filename) |
- |
- # Create forward declarations: allows other structs to reference |
- # each other |
- for entry in entities: |
- entry.PrintForwardDeclaration(header_fp) |
- print >>header_fp, '' |
- |
- for entry in entities: |
- entry.PrintTags(header_fp) |
- entry.PrintDeclaration(header_fp) |
- print >>header_fp, HeaderPostamble(filename) |
- header_fp.close() |
- |
- print >>sys.stderr, '... creating "%s"' % impl_file |
- impl_fp = open(impl_file, 'w') |
- print >>impl_fp, BodyPreamble(filename) |
- for entry in entities: |
- entry.PrintCode(impl_fp) |
- impl_fp.close() |
- |
-if __name__ == '__main__': |
- main(sys.argv) |